为什么TCP服务器会在接受连接后立即发送FIN?

时间:2010-10-06 07:26:49

标签: tcp

从ethreal数据包捕获中,我看到以下对我来说很奇怪的行为:

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.这会导致任何问题吗?

我的另一个疑问:

  1. 为什么有FIN,ACK?不应该只是FIN吗?该消息中ACK的含义是什么?
  2. 客户也不应该有FIN吗?
  3. 编辑: 经过一些分析,我发现如果文件描述符的数量超过限制,则服务器发送FIN。但是,在这种情况下,文件描述符似乎没有超出限制。对于其他情况会发生什么?

6 个答案:

答案 0 :(得分:9)

经过深入分析,发现以下问题是:

当客户端尝试TCP连接时,即使服务器当前没有调用accept,连接也会通过。如果服务器调用了“listen”函数,它将继续接受连接,直到达到积压限制。

但是,如果应用程序进程超出了它可以使用的最大文件描述符的限制,那么当服务器调用接受时,它会意识到没有可用于为套接字分配的文件描述符并且无法接受调用和TCP连接向另一方发送FIN。

我只是在这里发布这个发现。我仍然把接受的答案留给了哈比的那个答案。

感谢所有回答这个问题的人。

答案 1 :(得分:4)

FIN通常意味着套接字上的另一端叫shutdown(..)

答案 2 :(得分:1)

我猜测inetd或类似的守护程序正在接受连接,然后尝试forkexec另一个程序来处理连接,并且{ {1}}失败(由于资源耗尽)或fork失败(由于文件不存在,权限错误等原因)。

答案 3 :(得分:1)

可能是TCP wrappers。如果服务器进程是使用libwrap支持构建的,它将接受连接,检查/etc/hosts.allow/etc/hosts.deny,然后在策略拒绝时立即关闭连接。

很容易看出服务器是否使用了libwrap:

> ldd /usr/sbin/sshd | grep libwrap
libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f1562d44000)

答案 4 :(得分:0)

似乎服务器在接受连接后很快就会调用shutdown

答案 5 :(得分:0)

我认为FIN是通过调用close()而不是shutdown()发送的。

该连接在积压队列中;在accept()之后,服务器出于任何原因决定终止它(例如TCP包装器ACL或文件描述符不足)。在这种情况下,close()将文件描述符(FD)的链接数减少1到0,因此此连接的FD被完全破坏。然后,客户端从服务器的角度将数据发送到不存在的套接字,服务器必须响应RST。

如果它是shutdown(),服务器仍然可以恢复客户端发送的数据,并且必须等待客户端的FIN正常关闭连接。没有RST返回。

p.s。 enter image description here