tcp堆栈如何区分关闭和关闭?

时间:2012-03-22 09:47:16

标签: tcp

我们知道:

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

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 - &gt; syn

02&lt; - syn,ack

03 - &gt; ack

04 - &gt; fin,ack

05&lt; - ack

...

netstat -an | grep 192.168.1.100

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


来自wireshark的输出,似乎关闭和关闭没有什么不同,

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

那为什么行为不同?

1 个答案:

答案 0 :(得分:11)

关闭套接字和执行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)。