挪用 close()/closesocket() 函数意味着完整断开衔接,即不克不及发送数据也不克不及接纳数据,这种“僵硬”的方法有时分会显得不太“优雅”。


图1:close()/closesocket() 断开衔接


上图演示了两台正在停止双向通讯的主机。主机A发送完数据后,片面挪用 close()/closesocket() 断开衔接,之后主机A、B都不克不及再承受对方传输的数据。实践上,是完整无法挪用与数据收发有关的函数。
普通状况下这不会有成绩,但有些特别时辰,需求只断开一条数据传输通道,而保存另一条。
运用 shutdown() 函数可以到达这个目标,它的原型为:

int shutdown(int sock, int howto); //Linux int shutdown(SOCKET s, int howto); //Windows

sock 为需求断开的套接字,howto 为断开方法。
howto 在 Linux 下有以下取值:

  • SHUT_RD:断开输出流。套接字无法接纳数据(即便输出缓冲区收到数据也被抹去),无法挪用输出相干函数。

  • SHUT_WR:断开输入流。套接字无法发送数据,但假如输入缓冲区中还有未传输的数据,则将传递到目的主机。

  • SHUT_RDWR:同时断开 I/O 流。相当于分两次挪用 shutdown(),个中一次以 SHUT_RD 为参数,另一次以 SHUT_WR 为参数。


howto 在 Windows 下有以下取值:

  • SD_RECEIVE:封闭接纳操作,也就是断开输出流。

  • SD_SEND:封闭发送操作,也就是断开输入流。

  • SD_BOTH:同时封闭接纳和发送操作。


至于什么时分需求挪用 shutdown() 函数,下节我们会以文件传输为例停止解说。

close()/closesocket()和shutdown()的差别

确实地说,close() / closesocket() 用来封闭套接字,将套接字描绘符(或句柄)从内存肃清,之后再也不克不及运用该套接字,与C言语中的 fclose() 相似。使用程序封闭套接字后,与该套接字相干的衔接弛缓存也得到了意义,TCP协定会主动触发封闭衔接的操作。
shutdown() 用来封闭衔接,而不是套接字,不论挪用若干次 shutdown(),套接字仍然存在,直到挪用 close() / closesocket() 将套接字从内存肃清。
挪用 close()/closesocket() 封闭套接字时,或挪用 shutdown() 封闭输入流时,都邑向对方发送 FIN 包。FIN 包表现数据传输终了,盘算机收到 FIN 包就晓得不会再无数据传送过去了。
默许状况下,close()/closesocket() 会立刻向收集中发送FIN包,不论输入缓冲区中能否还无数据,而shutdown() 会等输入缓冲区中的数据传输终了再发送FIN包。也就意味着,挪用 close()/closesocket() 将丧失输入缓冲区中的数据,而挪用 shutdown() 不会。