two servers listening on same port ?

S

sc_wizard29

hi everyone,

This ones makes me scratch my head : I'm using the following script on
Windows and it looks like I can run two instances of it
simultaneously...which means that I have 2 servers listening on the
same port.

#!/usr/bin/perl -w
use strict;
use Socket;
my $port = 8080;
my $proto = getprotobyname('tcp');
socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die
"setsockopt: $!";
bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";
listen(Server,SOMAXCONN) || die "listen: $!";
print "Server : server started on port $port\n";
while(1) {}

I was expecting an error like "port already in use". Am I doing
something wrong ?
 
S

Sisyphus

hi everyone,

This ones makes me scratch my head : I'm using the following script on
Windows and it looks like I can run two instances of it
simultaneously...which means that I have 2 servers listening on the
same port.

I have just been bitten by the same thing on Windows 2000 - during the
tidying up of some server and client scripts. I started getting inconsistent
behaviour that really had me puzzled (and irate) ... until I realised I had
four instances of the server script running concurrently - all listening to
the same port.

Not sure of the "approved" method for determining whether a port is in use.
As an interim measure I'm doing the following in an attempt to make sure I
don't make the same mistake again:

my $server_port = '2004'; # or whatever
my $netstat = `netstat -an`;
if($netstat =~ /:$server_port\s/) {die "Port already in use"}
# Followed by code to create the server listening on
# port $server_port

Cheers,
Rob
 
A

Anno Siegel

Sisyphus said:
hi everyone,

This ones makes me scratch my head : I'm using the following script on
Windows and it looks like I can run two instances of it
simultaneously...which means that I have 2 servers listening on the
same port.
[...]

Not sure of the "approved" method for determining whether a port is in
use.

As filehandles, sockets are flock-able. An exclusive lock in the
server should do:

flock $server, LOCK_EX | LOCK_NB or die "port in use";

(Untested, I can't open the port another time in the first place.)

Anno
 
S

Sisyphus

..
..
As filehandles, sockets are flock-able. An exclusive lock in the
server should do:

flock $server, LOCK_EX | LOCK_NB or die "port in use";

Also not sure about the use of flock() on Win32. When I insert the above
code into my server script (which runs with warnings pragma enabled) it dies
with:

Argument "LOCK_OZ" isn't numeric in flock at file_server.plx line 35.
port in use at file_server.plx line 35.

Line 35 is simply the line that implements the above code - the port is
definitely not in use.

From 'perldoc -f flock' I find:
"Produces a fatal error if used on a machine that doesn't implement
flock(2), fcntl(2) locking, or lockf(3)."

'perldoc perlport' reports that fcntl() is not implemented on Win32, though
flock() *is* implemented ... not sure what to make of all that.

Sorry if I'm being dumb.

Cheers,
Rob
 
T

Thomas Kratz

hi everyone,

This ones makes me scratch my head : I'm using the following script on
Windows and it looks like I can run two instances of it
simultaneously...which means that I have 2 servers listening on the
same port.

#!/usr/bin/perl -w
use strict;
use Socket;
my $port = 8080;
my $proto = getprotobyname('tcp');
socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die
"setsockopt: $!";

Get rid of the SO_REUSEADDR. IIRC this will have the disadvantage that you
may have to wait a bit before you can reopen the socket after a close.
bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";
listen(Server,SOMAXCONN) || die "listen: $!";
print "Server : server started on port $port\n";
while(1) {}

I was expecting an error like "port already in use". Am I doing
something wrong ?

You might find IO::Socket easier to use.

Thomas

--
$/=$,,$_=<DATA>,s,(.*),$1,see;__END__
s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~
$_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
'%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e.r^.>l^..>k^.-
 
S

Sisyphus

..
..
You might find IO::Socket easier to use.

Yes - that's what *I* use - but it still permits multiple instances of
servers to be listening on the same port.

Seems to be a Win32 thing - on linux I find it's not possible to run
multiple instances of the same server script. I get the fatal error "Address
already in use".

Even with the latest CPAN release of IO, the behaviour persists on Win32.
Should this be submitted as a bug to
http://rt.cpan.org/Public/Dist/Display.html?Name=IO ?

Cheers,
Rob
 
A

Anno Siegel

Sisyphus said:
.
.

Also not sure about the use of flock() on Win32. When I insert the above
code into my server script (which runs with warnings pragma enabled) it
dies with:

Argument "LOCK_OZ" isn't numeric in flock at file_server.plx line 35.
port in use at file_server.plx line 35.

LOCK_OZ? Whazzat? Some windowy specialty?
Line 35 is simply the line that implements the above code - the port is
definitely not in use.

From 'perldoc -f flock' I find:
"Produces a fatal error if used on a machine that doesn't implement
flock(2), fcntl(2) locking, or lockf(3)."

'perldoc perlport' reports that fcntl() is not implemented on Win32,
though flock() *is* implemented ... not sure what to make of all that.

I have no personal experience with Windows, but I thought that file
locking worked.

Anno
 
S

sc_wizard29

Looks like the use of netstat before the binding is the most "direct"
solution...

Here is the same script with IO::Socket (the problem is the same but
the script is shorter ;)

#!/usr/bin/perl -w
use strict;
use IO::Socket;
my $port=8080;
my $server = IO::Socket::INET->new(Proto => 'tcp',
LocalPort => $port,
Listen => SOMAXCONN,
Reuse => 1);
die "can't setup server" unless $server;
print "Server : server started on port $port\n";
while(1) {}
 
B

Ben Morrow

Quoth (e-mail address removed)-berlin.de:
Sisyphus said:
hi everyone,

This ones makes me scratch my head : I'm using the following script on
Windows and it looks like I can run two instances of it
simultaneously...which means that I have 2 servers listening on the
same port.
[...]

Not sure of the "approved" method for determining whether a port is in
use.

As filehandles, sockets are flock-able.

I *seriously* doubt if they are on Win32. Sockets on Win32 are not
ordinary filehandles, perl just fakes them up to look like it.

To the OP: remove the SO_REUSEADDR. Winsock is *COMPLETELY* broken;
among other things, SO_REUSEADDR doesn't mean 'allow another process to
bind again after the socket is closed but before the wait period' but
actually means 'bind to this port even if there is another process bound
there, at which point both sockets become non-deterministic' !!

See http://msdn.microsoft.com/library/default.asp?url=/library/en-us
/winsock/winsock/using_so_reuseaddr_and_so_exclusiveaddruse.asp

(please excuse the wrapping).

Ben
 
S

Sisyphus

..
..
LOCK_OZ? Whazzat? Some windowy specialty?

or maybe an Aussie specialty :)
I have no personal experience with Windows, but I thought that file
locking worked.

Heh ... I had this notion that it worked on Win32 without even being
specifically invoked :)

Btw, I (inadvertently) omitted some relevant info from my reply - if I run
under strictures I get:

Bareword "LOCK_EX" not allowed while "strict subs" in use at file_server.plx
line 35.
Bareword "LOCK_NB" not allowed while "strict subs" in use at file_server.plx
line 35.

Without strictures the error is as I reported.

I tried not supplying a second argument, but perl insists that a second arg
be supplied. I'm not feeling very energetic about this at the moment ....
maybe later :)

Cheers,
Rob
 
T

Thomas Kratz

Sisyphus said:
.
.



Yes - that's what *I* use - but it still permits multiple instances of
servers to be listening on the same port.

No to me it does not. Using:

my $srv = IO::Socket::INET->new(
Proto => 'tcp',
LocalPort => 4016,
Listen => SOMAXCONN,
ReuseAddr => 0,
);

the second instance fails reporting 'Unknown error' ($!).
Seems to be a Win32 thing - on linux I find it's not possible to run
multiple instances of the same server script. I get the fatal error "Address
already in use".

In Winsock 2 there is a new socket option called SO_EXCLUSIVEADDRUSE.
http://msdn.microsoft.com/library/d...winsock/winsock/using_so_exclusiveaddruse.asp
Even with the latest CPAN release of IO, the behaviour persists on Win32.
Should this be submitted as a bug to
http://rt.cpan.org/Public/Dist/Display.html?Name=IO ?

I don't think it's a bug. More a winsock "feature".

Thomas


--
$/=$,,$_=<DATA>,s,(.*),$1,see;__END__
s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~
$_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
'%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e.r^.>l^..>k^.-
 
B

Ben Morrow

Quoth (e-mail address removed):
Looks like the use of netstat before the binding is the most "direct"
solution...

No, omit the SO_REUSEADDR...
Here is the same script with IO::Socket (the problem is the same but
the script is shorter ;)

#!/usr/bin/perl -w
use strict;
use IO::Socket;
my $port=8080;
my $server = IO::Socket::INET->new(Proto => 'tcp',
LocalPort => $port,
Listen => SOMAXCONN,
Reuse => 1);
^^^^^^^^^^^^^^
....or this.

Ben
 
B

Ben Morrow

Quoth "Sisyphus said:
or maybe an Aussie specialty :)


Heh ... I had this notion that it worked on Win32 without even being
specifically invoked :)

Opening a file takes a mandatory lock, unless you ask it not to.
Btw, I (inadvertently) omitted some relevant info from my reply - if I run
under strictures I get:

Bareword "LOCK_EX" not allowed while "strict subs" in use at file_server.plx
line 35.
Bareword "LOCK_NB" not allowed while "strict subs" in use at file_server.plx
line 35.

Without strictures the error is as I reported.

<giggle>

If you don't import those constants from the Fcntl module, then Perl
(without strict) will treat them as unquoted strings. Then we have

~% perl -le'print "LOCK_EX" | "LOCK_NB"'
LOCK_OZ

Have you *really* never used flock before?

Ben
 
G

Gunnar Hjalmarsson

Anno said:
I have no personal experience with Windows, but I thought that file
locking worked.

IIRC, flock() causes a fatal error on Windows 95/98, but works on later
Windows versions.
 
S

Sisyphus

Thomas Kratz said:
No to me it does not. Using:

my $srv = IO::Socket::INET->new(
Proto => 'tcp',
LocalPort => 4016,
Listen => SOMAXCONN,
ReuseAddr => 0,
);

the second instance fails reporting 'Unknown error' ($!).

Yep - there was a stray 'Reuse => 1' in the constructor that was causing my
problem on Windows - no doubt the result of a mindless copy'n'paste
somewhere along the way. Removing it removed the need for that awful netstat
kludge.

Cheers,
Rob
 
S

sc_wizard29

Thanks everyone for your answers... here are two versions of a simple
server that "solve" the multiple binding problem on windows (for the
ones too busy to read all the replies ;)

#!/usr/bin/perl -w
use strict;
use Socket;
my $port = 2000;
my $proto = getprotobyname('tcp');
socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";
listen(Server,SOMAXCONN) || die "listen: $!";
print "Server : server started on port $port\n";
while(1) {}

#!/usr/bin/perl -w
use strict;
use IO::Socket;
my $port=8080;
my $server = IO::Socket::INET->new(Proto => 'tcp',
LocalPort => $port,
Listen => SOMAXCONN);
die "can't setup server" unless $server;
print "Server : server started on port $port\n";
while(1) {}
 
B

Big and Blue

Ben said:
To the OP: remove the SO_REUSEADDR. Winsock is *COMPLETELY* broken;

I think you've missed the point - Microsoft *is* the standard (the MS
definition of a standard is "used by MS"). It's everything else which is
wrong. The fact that MS is completely broken here doesn't matter....
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top