从ethereal数据包捕获,我看到以下行为,这对我来说很奇怪:
Client --> Server [SYN]
Server --> Client [SYN, ACK]
Client --> Server [ACK]
Server --> Client [FIN, ACK]
Client --> Server [ACK]
Client --> Server [TCP Segment of a reassembled PDU] (I don't know what this means)
Server --> Client [RST]
关于为什么会发生这种情况的任何想法?
此外,服务器端口是6000.这会导致任何问题吗?
我的另一个疑问:
编辑:经过一些分析后,我发现文件描述符的数量是否已超过限制,然后服务器发送FIN。但是,在这种情况下,文件描述符似乎没有超出限制。对于其他情况,这会发生什么?
FIN通常意味着另一方在套接字上称为shutdown(..)
。
经过深入分析,发现以下问题是:
当客户端尝试TCP连接时,即使服务器当前没有调用accept,连接也会通过。如果服务器调用了“listen”函数并且它将继续接受连接直到达到积压限制,则会发生这种情况。
但是,如果应用程序进程超出了它可以使用的最大文件描述符的限制,那么当服务器调用接受时,它会意识到没有可用于为套接字分配的文件描述符并且无法接受调用和TCP连接发送FIN到另一边。
我只是想在这里发布这个发现。我仍然把接受的答案留给了哈比的答案。
感谢所有回答这个问题的人。
我猜这个连接被inetd
或类似的守护进程接受,然后尝试fork
和exec
另一个程序来处理连接,并且fork
失败(由于资源耗尽)或exec
失败(到期)到不存在的文件,权限错误等)。
可能是TCP wrappers。如果服务器进程是使用libwrap支持构建的,它将接受连接,检查/etc/hosts.allow
和/etc/hosts.deny
,然后在策略拒绝时立即关闭连接。
很容易看出服务器是否使用libwrap:
> ldd /usr/sbin/sshd | grep libwrap
libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f1562d44000)
似乎服务器在接受连接后很快就会调用shutdown
。
我认为FIN是通过调用close()而不是shutdown()来发送的。
连接在积压队列中;在accept()之后,服务器决定因任何原因终止它(例如TCP包装器ACL或文件描述符)。在这种情况下,close()会将文件描述符(FD)的链接数减少1到0,因此此连接的FD将被完全销毁。之后,客户端从服务器的角度将数据发送到不存在的套接字,服务器必须响应RST。
如果是shutdown(),服务器仍然可以恢复客户端发送的数据,并且必须等待来自客户端的FIN才能正常关闭连接。没有退回RST。