![](/img/trans.png)
[英]Why app can accept and read/write TCP connection in CLOSE_WAIT state (Linux)?
[英]Linux tcp server can't bind to a close_wait port
我试图让tcp服务器绑定到close_wait端口,但是它导致了Errno::EADDRINUSE
错误。
我创建了一个侦听端口55555的tcp服务器。然后,客户端连接到该服务器。 经过一些操作后,运行ss -at | grep 55555
ss -at | grep 55555
。
# ss -at | grep 55555
LISTEN 0 128 *:55555 *:*
FIN-WAIT-2 0 0 127.0.0.1:55555 127.0.0.1:16413
CLOSE-WAIT 0 0 127.0.0.1:16413 127.0.0.1:55555
我试图绑定端口16413
,这导致了Errno::EADDRINUSE
错误。 但是,如果我连接到ESTAB套接字,则该套接字可以绑定到端口(例如下面的22385)。
# ss -at | grep 55555
LISTEN 0 128 *:55555 *:*
ESTAB 0 0 127.0.0.1:22385 127.0.0.1:55555
ESTAB 0 0 127.0.0.1:55555 127.0.0.1:22385
一些脚本被ruby重现了问题。
tcp_server_close_wait.rb
require 'socket'
server = TCPServer.new 55555 # Server bind to port 2000
loop do
client = server.accept # Wait for a client to connect
client.puts "Hello !"
client.puts "Time is #{Time.now}"
client.shutdown(Socket::SHUT_WR)
end
tcp_server.rb
require 'socket'
server = TCPServer.new 55555 # Server bind to port 2000
loop do
client = server.accept # Wait for a client to connect
client.puts "Hello !"
client.puts "Time is #{Time.now}"
client.close
end
tcp_client.rb
require 'socket'
include Socket::Constants
socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
sockaddr = Socket.pack_sockaddr_in( 55555, '127.0.0.1' )
socket.connect( sockaddr )
res = socket.read
puts res
sleep 10000
** tcp_bind.rb **
require 'socket'
# use Addrinfo
socket = Socket.new(:INET, :STREAM, 0)
socket.bind(Addrinfo.tcp("0.0.0.0", ARGV[0].to_i))
创建close_wait
绑定。
运行ruby tcp_server_close_wait.rb
运行ruby tcp_client.rb
运行ss -at | grep 55555
ss -at | grep 55555
查找客户端端口
运行ruby tcp_bind.rb $client_port
创建ESTAB
绑定。 1.运行ruby tcp_server.rb
运行ruby tcp_client.rb
运行ss -at | grep 55555
ss -at | grep 55555
查找客户端端口
运行ruby tcp_bind.rb $client_port
我使用C程序对Linux 4.4.74-18.20重复了相同的测试。
我得到的结果与OP不同。
禁用SO_REUSEPORT时,两个端口的绑定均失败:
启用SO_REUSEPORT(针对所有套接字)后,两个端口的绑定成功。
有关获得有关SO_REUSEPORT的更多信息,请参见socket(7)手册页 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.