socket shutdown

如何优雅的关闭socket——shutdown()

背景

socket通信的应用那真是太多了。这次的项目是本地的多进程的通信。由于是windows进程通信中不支持msg,又不想把东西搞得太复杂,最后探讨的结果就是用socket进行连接通信。

由于没有明确的结束协议(因为内部有多线程的交流,到底谁是最后一个很难规定),所以在socket close之后,由于socket被占用,导致进程无法结束。从现象上看就是假死的感觉。(rcv哪里还是在接收的阻塞状态)

最初的解决案是自己发一个假的结束信号,socket内部的rcv接收到后,判断是否为结束信号。是的话退出rcv,但是发现不是每次都灵光。最后下定决心上网上找个优雅的解决方法。

shutdown

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

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:同时关闭接收和发送操作。

断开不意味着结束,资源也没有消失,所以正确的做法还应该继续close。

bool DbgSocketIf::disconnectSrv()
{
#if defined(__linux__) 
    shutdown(sClinet, SHUT_RDWR);
    close(sClient);
#else
    shutdown(sClinet, SD_BOTH);
    closesocket(sClient);
    WSACleanup();
#endif
    return true;
}
posted @ 2022-02-10 15:08  桥下听雨  阅读(434)  评论(0编辑  收藏  举报