Windows 2012 R2 与 Linux Centos7 之间的 TCP 套接字连接错误

Windows 2012 R2 与 Linux Centos7 之间的 TCP 套接字连接错误

我在 Windows 2012 R2 计算机和 Linux CentOS7 之间的 TCP 套接字连接方面遇到了问题。当我运行 perl 客户端,从 Linux 向 Windows perl 服务发送多条消息时,它始终工作正常。但是,如果我从 Windows 向 Linux 服务运行相同的客户端,有时它不会连接,并且需要大约 60 秒才能恢复。当两个客户端几乎同时执行时,就会发生这种情况。就好像 Linux 在向 Windows 发送消息后暂时关闭了所有监听端口一样。我也尝试过用 C 编写的客户端/服务器,情况也一样。

这是客户端代码

#!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) }

    }


}

这就是服务器代码

#!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);
}

有人能帮帮我吗?我可以在 Centos 或 Windows 中配置什么来避免每次请求同时到达时出现这种烦人的 60 秒阻塞?

对于测试你可以运行服务器像这样:

Linux:

perl ./serv.pl 3201

视窗:

perl .\serv.pl 3202

运行客户端像这样:

Linux:

perl ./test_sendmsg.pl --msg="mensaje de prueba" --ip=replace_your_ip_windows --port=3202

视窗:

perl .\test_sendmsg.pl --msg="mensaje de prueba" --ip=replace_your_ip_linux --port=3201

答案1

我终于找到了解决方案!干扰 Windows 和 Centos7 之间连接的是我们在 /etc/sysctl.conf 中使用的以下配置:

    net.ipv4.tcp_tw_recycle = 1

我已将其更改为:

    net.ipv4.tcp_tw_recycle = 0

我已经使用该配置重新启动了 Centos7 上的网络,并且它在两个方向上发送 TCP 消息时没有再次失败。

相关内容