【问题标题】:how tcp stack distinguish close and shutdown?tcp stack如何区分close和shutdown?
【发布时间】:2012-03-26 09:12:39
【问题描述】:

我们知道:

/////////////////////////////////////// //////////

close() 将终止 tcp 连接上的两个方向

shutdown() 可以阻止一个或两个方向的通信

/////////////////////////////////////// //////////

这里,让我感到困惑的是 tcp stack 是如何区分它们的?

我已经写了一个示例程序:

首先我使用:

....
connect(192.168.1.100) //there is a server process running in 192.168.1.100
....
close(socketfd);
sleep(1000);

然后我使用wireshark转储数据包:

01 -->syn

02 <--syn,ack

03 -->ack

04 -->fin,ack

05 <--ack

netstat -an |grep 192.168.1.100

我已经运行了大约 5 分钟,它打印出来了:

一开始是"tcp 0 0 ... FIN_WAIT2",大约2分钟后没有输出,好像连接被破坏了。

然后,我使用:

....
connect(192.168.1.100)
....
shutdown(socketfd,SHUT_WR);
sleep(1000);

使用wireshark转储数据包:

01 -->同步

02

03 -->确认

04 -->fin,ack

05

...

netstat -an |grep 192.168.1.100

运行大约 10 分钟,它总是打印: “tcp 0 0 ... FIN_WAIT2”


从wireshark的输出来看,close和shutdown似乎没有区别,

但是从 netstat 的输出来看,它的行为是不同的。

那么为什么行为不同?

【问题讨论】:

    标签: tcp


    【解决方案1】:

    仅仅关闭套接字和执行shutdown(SHUT_RDWR) 在电线上没有区别。任何一个都会导致 TCP 堆栈发出 FIN 并停止接受来自另一端的数据包。唯一的区别在于您的程序:在shutdown 之后,文件描述符仍然有效,但在close 之后则无效。可以肯定的是,除了关闭 shutdown 之后仍然有效的文件描述符之外,您不能做太多事情,但它仍然有效。

    在您的情况下,您使用SHUT_WR,而不是SHUT_RDWR,因此您的套接字仍然准备好从另一端接收数据。但是您的服务器不发送任何数据。如果您的服务器在客户端关闭后发送了一些数据,您会看到closeshutdown(SHUT_WR) 之间的差异。 close() 客户端将使用 RST 响应服务器的数据,而 shutdown(SHUT_WR) 客户端将接受服务器的数据并确认它。 shutdown(SHUT_RDWR) 客户端的行为与close() 客户端相同。

    在大多数客户端-服务器 TCP 协议(​​例如 HTTP)中,服务器将在收到客户端的 FIN 后立即终止连接。因此,对于这些协议,客户端是半关闭还是完全关闭套接字并没有太大区别,因为无论如何服务器都会立即关闭其连接端。我可以看到您的服务器并没有这样的行为,因为我没有看到它发送自己的 FIN(只有您的客户端发送 FIN)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-17
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      • 2016-05-15
      相关资源
      最近更新 更多