tcp 堆栈如何区分关闭和关闭? [英] how tcp stack distinguish close and shutdown?

查看:26
本文介绍了tcp 堆栈如何区分关闭和关闭?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

众所周知:

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

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

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

close() will terminate both directions on a tcp connection

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

shutdown() can block communication in one or both directions

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

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

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

here,what puzzled me is how tcp stack can tell them apart?

我写了一个示例程序:

首先我使用:

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

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

then I use wireshark to dump the packets:

01 -->syn

02 <--syn,ack

03 -->ack

04 -->fin,ack

05 <--ack

netstat -an |grep 192.168.1.100

netstat -an |grep 192.168.1.100

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

I have run it for about 5 minutes, it print:

先是tcp 0 0 ... FIN_WAIT2",然后大约2分钟后没有输出,似乎连接被破坏了.

"tcp 0 0 ... FIN_WAIT2 " at first,then after about 2 minutes there is no output,seems that the connection has been destroyed.

然后,我使用:

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

使用wireshark转储数据包:

use wireshark to dump the packets:

01 -->同步

02 <--syn,ack

02 <--syn,ack

03 -->确认

04 -->鳍,确认

05 <--确认

...

netstat -an |grep 192.168.1.100

netstat -an |grep 192.168.1.100

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

run it for about 10 minutes, it always print: "tcp 0 0 ... FIN_WAIT2"

从wireshark的输出来看,好像close和shutdown没有区别,

from the output of wireshark ,it seems there is no different for close and shutdown,

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

but from the output of netstat ,its behaviour is different.

那么为什么行为不同呢?

so why the behaviour is different?

推荐答案

在关闭套接字和执行 shutdown(SHUT_RDWR) 之间没有区别.要么会导致 TCP 堆栈发出 FIN 并停止接受来自另一端的数据包.唯一的区别在于您的程序:在 shutdown 之后,文件描述符仍然有效,但在 close 之后就无效了.可以肯定的是,在 shutdown 之后你不能对仍然有效的文件描述符做很多事情,除了关闭它,但它仍然有效.

There is no difference on the wire between just closing the socket and doing shutdown(SHUT_RDWR). Either will cause the TCP stack to emit a FIN and stop accepting packets from the other end. The only difference is in your program: after shutdown the file descriptor remains valid, but after close it doesn't. To be sure, you cannot do much with the still-valid file descriptor after shutdown besides closing it, but it is valid nonetheless.

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

In your case you use SHUT_WR, not SHUT_RDWR, so your socket is still prepared to receive data from the other end. But your server doesn't send any data. You would see a difference between close and shutdown(SHUT_WR) if your server sent some data after the client had closed its end. The close() client would respond to the server's data with RST whereas the shutdown(SHUT_WR) client would accept the server's data and ACK it. A shutdown(SHUT_RDWR) client would behave the same as the close() client.

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

In most client-server TCP protocols (like HTTP for instance), the server will terminate its end of the connection anyway as soon as it receives a FIN from the client. So with those protocols it doesn't make much of a difference whether the client half-closes or full-closes the socket because the server will promptly close its end of the connection anyway. I can see that your server does not behave like this though, because I don't see it sending its own FIN (only your client sends a FIN).

这篇关于tcp 堆栈如何区分关闭和关闭?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆