socket中close()和shutdown()区别

Posted Dufre.WC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了socket中close()和shutdown()区别相关的知识,希望对你有一定的参考价值。

基本TCP程序socket函数

并发服务器

Unix中编写并发服务器最简单的办法是fork一个子进程来服务每个客户。
当一个连接建立时,accept返回,服务器接着调用fork,然后由子进程服务客户(通过已连接的套接字connfd),父进程则等待另一个连接(通过监听套接字listenfd)。新的客户由子进程提供服务,父进程就关闭已连接套接字。

如图:
1、服务器接收了一个客户请求

2、服务器调用fork,此时listenfd和connfd这两个描述符都在父进程和子进程之间共享(被复制)。

3、父进程关闭已连接套接字(connfd),由子进程关闭监听套接字(listenfd)

最终子进程处理与客户的连接,父进程则可以在监听套接字上在此调用accept来处理下一个客户连接。

close函数

close函数是用来关闭套接字

int close(int sockfd);

成功返回0,出错为-1

关闭已连接的套接字只是导致相应描述符的引用计数减1,如果引用计数扔大于0,这个close调用并不会让TCP连接上发送一个FIN。如果确实像发送一个FIN,可以用shutdown函数。

回到刚刚并发服务器的过程,第二步fork返回后,connfd和listenfd的引用计数均为2。第三步,父进程close套接字connfd,子进程close套接字listenfd后,connfd和listenfd的引用计数均为1。而该套接字真正的关闭是等于0才发生的。

需要注意的是第三步如果父进程对每个accept返回的已连接套接字connfd都不调用close,那么父进程最终将耗尽可用描述符,而且没有一个客户连接会被终止。因为子进程关闭connfd时,它的引用计数将由2减为1,因为父进程永不关闭任何已连接套接字。

shutdown函数

int shutdown(int sockfd,int howto);

成功返回0,出错返回-1

该函数的行为依赖howto参数的值:

  • SHUT_RD
    套接字中不再有数据可接收,而且套接字接收缓冲区中的现有数据都被丢弃。

  • SHUT_WR
    对于TCP套接字,称为半关闭(half-close)。当前在套接字发送缓冲区中的数据将被发送掉,后跟TCP的正常连接终止序列。(不管套接字的引用计数是否等于0)

  • SHUT_RDWR
    等于调用shutdown函数两次,连接的读半部和写半部都关闭。

区别

  • close把描述符的引用计数减1,仅在该计数变为0时关闭套接字。shutdown可以不管引用计数就激发TCP的正常连接终止序列

  • close终止读和写两个方向的数据发送。TCP是全双工的,有时候需要告知对方已经完成了数据传送,即使对方仍有数据要发送给我们。

以上是关于socket中close()和shutdown()区别的主要内容,如果未能解决你的问题,请参考以下文章

socket中close()和shutdown()区别

socket.shutdown 与 socket.close

socket链接的关闭连接与close和shutdown的区别

Linux socket shutdown()和close()

通过调用 shutdown 和 close 来关闭套接字

整理close 和 shutdown 的原理