2014-01-27 172 views
2

由于它在维基百科上撰写关闭TCP连接应该使用数据包FIN - >(FIN,ACK) - > ACK。但是,当我使用close()函数关闭套接字时,我看不到FIN数据包,从服务器到客户端立即发送(FIN,ACK)数据包,然后客户端通过发送(FIN,ACK)关闭连接,服务器响应ACK分组。那么丢失的FIN数据包在哪里(也许它合并到FIN,ACK)?FIN省略,FIN-ACK发送

+0

您确定服务器之前没有关闭连接吗?它看起来像服务器关闭连接 – hek2mgl

+0

我没有看到这样的过渡:http://blog.zhuzhaoyuan.com/wp-content/uploads/2009/03/tcp-states1.png 创建一个最小的tcpdump示例。 –

+0

当我使用close()函数关闭套接字时,我发现客户端发送FIN,ACK,然后服务器以ACK响应 – scdmb

回答

6

收盘顺序也可以是不同的,并不需要有相同的包内FIN + ACK:

  • ACK只是确认收到的数据(例如,接受一切都交给给出序列号)
  • 数据包将重新发送,直到收到一个ACK为止
  • FIN只是说发送FIN的端不会再发送任何数据。它不会提供任何信息,如果它仍然会收到数据。
  • 像其他分组FIN将被重新发送,直到接收被确认

协议(如HTTP)支持单面关机,例如客户端发送请求数据,然后发送FIN以通知服务器,它不会再发送数据。但它仍然会收到服务器发送的数据。服务器将像以前对所有数据所做的那样承认FIN。一旦服务器完成,它将发送它自己的客户端确认的FIN。在这种情况下,您有

1. client: FIN (will not send more) 
2. server: ACK (received the FIN) 
.. server: sends more data..., client ACKs these data 
3. server: FIN (will not send more) 
4. client: ACK (received the FIN) 

请注意,您在步骤#1中看到的数据包可能也有一个ACK。但是这个ACK只是确认服务器之前发送的数据。如果服务器没有更多的数据要发送,它可能会关闭连接。在这种情况下,步骤2 + 3可以合并,例如,服务器发送FIN + ACK,其中ACK确认客户端收到的FIN。

如果一方发送它的FIN,则连接称为半封闭。一旦双方发送它们的FIN并接收到FIN的ACK,无论它们是以3或4个数据包的形式进行传输,它都会被完全关闭。

+0

+1理解“ACK”的关键是它将**应用于指定的确认号码**。 'FIN' +'ACK'不是特殊**,除非**确认号码是_lastdatabyte + 1_(因为'FIN'按顺序号计数,就像'SYN'一样)。 –

+0

我猜RFC1122第4.2.3.2节是关键。我错了吗? – hek2mgl

+0

不是。这涉及延迟ACK等优化。关键是RFC793(例如RFC for TCP)部分3.5。但RFC不是一个容易阅读:) –

0

您必须已经收到FIN才能发送FIN/ACK。您是否因阅读EOS而关闭?

+0

我也这么认为,因为它在文档中。但你可以尝试使用telnet和wireshark。客户端真正发送'FIN,ACK'。然后服务器发送'FIN,ACK',最后客户端发送'ACK'。在Linux 3.2上观察到 – hek2mgl

+0

看起来好像有点可选,因为服务器只检查'FIN '设置。但是,我想这仍然有意义:) – hek2mgl

+0

不,它不是'可选的',它是RFC 793要求的。你能回答我的问题吗? – EJP