0

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
0

Finally I have found the solution! What was interfering between the connections among Windows and Centos7 was the following configuration, that we were using in the /etc/sysctl.conf:

    net.ipv4.tcp_tw_recycle = 1

I have changed it to:

    net.ipv4.tcp_tw_recycle = 0

I have rebooted the network on Centos7 with that configuration and it has not failed again sending TCP messages in both directions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.