Re: What's the best way to find an unused TCP port on the local system
by ikegami (Patriarch) on Oct 20, 2006 at 17:39 UTC
|
If using socket
Bind to port zero. The system will pick an unused port. You can find out the number of the port to which the socket was bound as follows:
use Socket qw( sockaddr_in );
my $port = (sockaddr_in(getsockname(SOCK)))[0];
print("Listening to port $port.\n");
If using IO::Socket/IO::Socket::INET
Don't specify a LocalPort or use LocalPort => 0. The system will pick an unused port. You can find out the number of the port to which the socket was bound as follows:
my $port = $sock->sockport();
print("Listening to port $port.\n");
Update: Added IO::Socket method.
| [reply] [d/l] [select] |
|
I have one more question. I'm interested in this problem of finding an unused port on a local system too. It's for some client/server based IPC. Given any method of those mentioned here (I prefer yours most), how would I go to communicate it to possible clients? One way could be to write that info into a (configuration) file, as the OP suggests. But that is somewhat unsatisfactory because if I wanted to make the processes communicate through files I may have chosen to do by means e.g. of a named pipe in the first place.
Of course I may set up a predefined port, and failing that, use a workaround. On the client side, if the server doesn't respond, and only then, the client itself may check a suitable file. However how do people generally deal with this problem? (If it is a problem at all...)
| [reply] |
|
It's hard to answer without knowing what you are doing. What's the difference between the server on port A and the one on port B? Or rather, why would someone want to connect to the server on port A as opposed to one on port B?
Generically speaking, the problem is the same as finding a someone's phone number. How do you that? Maybe you search a directory. Maybe you ask someone who knows. In both of these, you query an external system.
Therefore, a possible solution is to have the server communicate it's vitals to a directory server. The client (user or program) then selects the server to which it wishes to connect from the directory.
For example, ICQ used to work this way (before changes were made to fight spam and privacy invasion). The ICQ client would become a server and then connect to the central ICQ server. Someone wishing to send you a message would query the central ICQ server for your IP address.
Another example is battle.net. People wishing to play Starcraft over the internet log into the battle.net chat server (through the game). When someone creates (hosts) a game, Starcraft contacts battle.net letting it know at which IP the game resides. battle.net would present a list of running games to users and passes on the IP address and port to people wanting to join.
Update: Added examples.
| [reply] |
|
| [reply] |
|
That's a good trick to know, but it won't work for me, since the server I'm starting is written in C++. My Perl code is an external controller for the server and will also act as a client.
(UPDATE: FYI it's a test script)
--DrWhy
"If God had meant for us to think for ourselves he would have given us brains. Oh, wait..."
| [reply] |
|
This is not a Perl "trick". It's a feature of the system's socket library. You can use port 0 in C++ as well.
| [reply] |
|
|
|
Hmm... if I just want to know which next port (starting from e.g. 1025)
is free, but without binding to it (e.g. to pass the port number to an
external program) - how can that be done? I'm doing an (unportable)
system "lsof -i :$port" in ssh chain to check whether it's busy. Is there a better (portable) way?
cheers,
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [d/l] |
|
No, it's not possible. Such a feature would unavoidably introduce a race condition. Your child process needs to either communicate the port back to you, or must inherit the opened socket from you.
| [reply] |
Re: What's the best way to find an unused TCP port on the local system
by samtregar (Abbot) on Oct 20, 2006 at 17:37 UTC
|
I think you'll end up with a race-condition if you try to look at all open ports and then pick one. Instead, why not start at a fixed base and work your way up till you find an open one? Just keep $port++ till you find one that's free.
-sam
| [reply] [d/l] |
|
Yeah, I'm willing to live with a small race condition here. This is an internal tool and the frequency with which the tool is used means that the frequency at which two servers would run at the same time is very low, and thus the probability of the race condition become a concern is extremely low indeed.
Since this server is actually a c++ app and I have to communicate the port number by writing a new configuration file each time I don't want to muck with catching a failed startup, determine if it's because the port was in use, write a new config file and try again.
--DrWhy
"If God had meant for us to think for ourselves he would have given us brains. Oh, wait..."
| [reply] |