使用TCP关闭(sock,SHUT_RD)的行为

时间:2009-04-11 21:39:21

标签: networking sockets network-programming tcp

使用TCP套接字时,

是什么
shutdown(sock, SHUT_RD);
实际上呢?是否仅使所有recv()次调用返回错误代码?如果是这样,哪个错误代码?

是否会导致底层TCP连接发送任何数据包?对方在此时发送的任何数据会发生什么 - 它是否保留,连接的窗口大小是否一直缩小,直到达到0,或者它是否被丢弃,窗口大小不会缩小?

6 个答案:

答案 0 :(得分:4)

关闭套接字的读取端将导致任何阻塞的recv(或类似)调用返回0(表示正常关闭)。我不知道当前在IP堆栈上传输的数据会发生什么。它肯定会忽略来自另一方的数据。它根本不会影响对该套接字的写入。

事实上,明智地使用shutdown是确保您在完成后立即清理的好方法。不使用keepalive的HTTP客户端可以在发送请求后立即关闭写入端,看到Connection: closed的服务器也可以在收到后立即关闭读取端。请求。这将导致任何进一步的错误活动立即显而易见,这在编写协议级代码时非常有用。

答案 1 :(得分:3)

shutdown(,SHUT_RD)在TCP协议中没有任何对应物,所以当有人写入一个连接时,如果有人写入另一方表示它将无法读取或当您尝试读取后,它几乎可以实现你宣称你不会。

在略低的级别上,记住TCP连接是一对流,使用对等方发送数据直到它们声明它们已完成(通过发送FIN的SHUT_WR)是有益的。这两个流程是相当独立的。

答案 2 :(得分:2)

查看Linux源代码,shutdown(sock, SHUT_RD)似乎不会导致套接字状态发生任何变化。 (显然,shutdown(sock, SHUT_WR)会导致设置FIN。)

我不能评论窗口大小的变化(或缺少)。但你可以写一个测试程序来看。只需让inetd运行chargen服务,然后连接即可。 : - )

答案 3 :(得分:1)

我在Ubuntu 12.04上测试shudown(sock,SHUT_RD)。我发现当你在TCP缓冲区中没有任何类型的数据(包括FIN ....)时调用shutdown(sock,SHUT_RD),连续的读取调用将return 0(表示流的结束)。但是如果有一些数据在关闭函数之前或之后到达,则read调用将正常处理,就像没有调用shutdown函数一样。似乎shutdown(sock,SHUT_RD)不会导致任何TCP状态更改为套接字

答案 4 :(得分:0)

shutdown(sock,SHUT_RD)导致套接字的任何写入器接收到sigpipe信号。

使用read系统调用的任何进一步读取将返回-1并将errno设置为EINVAL。

使用recv将返回-1并设置errno以指示错误(可能是ENOTCONN或ENOTSOCK)。

答案 5 :(得分:0)

它有两种效果,其中一种与平台有关。

  1. recv()将返回零,表示流结束。
  2. 对等体对连接的任何进一步写入将是(a)由接收器(BSD)静默丢弃,(b)由接收器缓冲并最终导致send()阻塞或返回-1 / EAGAIN / EWOULDBLOCK(Linux),或(c)使接收方发送RST(Windows)。