当您必须通知远程客户端不再发送数据时,shutdown 很有用。您可以在shutdown()参数中指定要关闭哪个半通道。
最常见的情况是,您希望通过调用 shutdown(1) 来关闭 TX 半通道。在TCP层面,它发送一个FIN数据包,如果在read()上阻塞,远端会收到0字节,但远端仍然可以发回数据,因为RX半通道仍然打开。
一些应用程序协议使用它来表示消息的结束。其他一些协议根据数据本身找到 EOM。例如,在交互式协议中(消息被多次交换),可能没有机会或不需要关闭半通道。
在 HTTP 中,shutdown(1) 是客户端可以用来表示 HTTP 请求已完成的一种方法。但是 HTTP 协议本身嵌入了数据,可以检测请求的结束位置,因此多个请求的 HTTP 连接仍然是可能的。
我不认为在 close() 之前调用 shutdown() 总是必要的,除非您需要显式关闭半通道。如果您想停止所有通信, close() 也会这样做。调用shutdown()而忘记调用close()更糟糕,因为文件描述符资源没有被释放。
来自 Wikipedia:“在 SVR4 系统上使用 close() 可能会丢弃数据。在这些系统上可能需要使用 shutdown() 或 SO_LINGER 以保证所有数据的传递。”这意味着,如果您在输出缓冲区中有未完成的数据,则 close() 可以在 SVR4 系统上立即丢弃这些数据。 Linux、BSD 和基于 BSD 的系统(如 Apple)不是 SVR4, 会尝试在 close() 之后完整发送输出缓冲区。我不确定现在是否有任何主要的商业 UNIX 仍然是 SVR4。
再次以 HTTP 为例,在 SVR4 上运行的 HTTP 客户端使用 close() 不会丢失数据,因为它会在请求获得响应后保持连接打开。 SVR 下的 HTTP 服务器必须更加小心,在发送整个响应之后在 close() 之前调用 shutdown(2),因为响应将部分在输出缓冲区中。