Windows-Server-2012-R2
Windows 2012 R2 和 Linux Centos7 之間的 TCP 套接字連接錯誤
我在 Windows 2012 R2 機器和 Linux CentOS7 之間的 TCP 套接字連接問題。當我執行一個從 Linux 向 Windows perl 服務發送多條消息的 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
終於我找到了解決方案!干擾 Windows 和 Centos7 之間連接的是以下配置,我們在 /etc/sysctl.conf 中使用:
net.ipv4.tcp_tw_recycle = 1
我已將其更改為:
net.ipv4.tcp_tw_recycle = 0
我已經使用該配置重新啟動了 Centos7 上的網路,並且它再次雙向發送 TCP 消息並沒有失敗。