I have a connection problem with TCP sockets between a Windows 2012 R2 machine and Linux CentOS7. When I run a perl client that sends several messages from Linux to a Windows perl service, it allways works fine. But if I run the same client from Windows to Linux service, sometimes it does not connect and it takes approximately 60 seconds to recover. This happens when both clients are executed almost simultaneously. As if Linux had closed all the listening ports for a while after sending messages to Windows. I've also tried a client / server in C, and it's the same.
This is the client code:
#!perl
use Socket;
use Getopt::Long;
use Time::HiRes;
GetOptions( "msg=s" => \$msg,
"ip=s" => \$server,
"port=s" => \$port );
$y=20;
$totalTime=0;
for(my $i=0;$i<$y;$i++){
$ti=Time::HiRes::time();
&gjmsimplecli($msg.' '.$i, $server, $port);
$TestTime{"Result"} = Time::HiRes::time() - $ti;
$totalTime += $TestTime{"Result"};
print "Test $i \t[$TestTime{Result}] server [$server] port [$port]\n";
if ($TestTime{Result}>40){
$contadordemora++;
push(@demora,$i);
}
}
$promedio=$totalTime / $y;
print "Tiempo Promedio: [$promedio]\n";
print "Mensajes con demoras [$contadordemora] \n[@demora]\n";
sub gjmsimplecli {
my $msg = shift;
my $server = shift; # Host IP running the server
my $port = shift; # Host IP running the server
my $len = length($msg2JM);
$msg .= '#'x(1024-$len);
my $maxretrieve = 100;
my $retrieve = $maxretrieve;
my $msge = '';
while($retrieve){
if ($retrieve<100) { print " Retrieve - Last socket [$t11] connect [$t22] syswrite [$t33] sec\n"; }
$retrieve--;
$msge = '';
$t00 = Time::HiRes::time();
# create the socket, connect to the port
socket($socket,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
or $msge= "Error socket: $!";
$t11 = Time::HiRes::time() - $t00;
if ($msge ne '') { next; }
connect( $socket, pack_sockaddr_in($port, inet_aton($server)))
or $msge= "Error connect: $!";
$t22 = Time::HiRes::time() - $t00;
if ($msge ne '') { close($socket); next; }
syswrite $socket, $msg, 1024 or $msge = "Error syswrite: $!";
$t33 = Time::HiRes::time() - $t00;
if ($msge eq '') { $retrieve = 0; }
select(undef, undef, undef, 0.01);
if ($socket) { close($socket) }
}
}
And this is the server code:
#!perl
# Filename : server.pl
use POSIX;
use Socket;
sub makelisten {
my ( $proto );
#port and protocol
$port = shift || 3201;
$proto = getprotobyname('tcp') or die("getprotobyname: cannot get proto: $!");
#bind at inet address
socket( LISTFD, PF_INET, SOCK_STREAM, $proto );
setsockopt( LISTFD, SOL_SOCKET, SO_REUSEADDR, 1 );
setsockopt( LISTFD, SOL_SOCKET, SO_LINGER,pack("II",1,10)) or die "Can't set SO_LINGER: $!";
bind( LISTFD, sockaddr_in( $port, INADDR_ANY ) ) or die("bind: $!");
listen( LISTFD, SOMAXCONN ) or die("listen: $!");
return LISTFD;
}
$LISTFD=makelisten(shift);
print "SERVER started on port $port\n";
LOOP: while (1) {
my ($NEW_SOCKET,$msg);
unless (my $paddr = accept($NEW_SOCKET, $LISTFD) ) { close($NEW_SOCKET); next LOOP; }
# First socket reading
sysread $NEW_SOCKET, $msg, 1024||print " Error getting the message: $!";
close($NEW_SOCKET);
$msg =~ s/#+$//g;
print "gsimple msg [$msg]\n";
select(undef, undef, undef, 0.01);
}
Can someone help me? What can I configure in Centos or in Windows to avoid this annoying block of 60 seconds each time the requests arrive at the same time?
For the test you can run the server like this:
Linux:
perl ./serv.pl 3201
Windows:
perl .\serv.pl 3202
Run the clients like this:
Linux:
perl ./test_sendmsg.pl --msg="mensaje de prueba" --ip=replace_your_ip_windows --port=3202
Windows:
perl .\test_sendmsg.pl --msg="mensaje de prueba" --ip=replace_your_ip_linux --port=3201