close()函数:
int close(int sockfd); //返回成功为0,出错为-1.
-
close 一个套接字的默认行为是把套接字标记为已关闭,然后立即返回到调用进程,该套接字描述符不能再由调用进程使用,也就是说它不能再作为read或write的第一个参数,然而TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP连接终止序列。
-
在多进程并发服务器中,父子进程共享着套接字,套接字描述符引用计数记录着共享着的进程个数,当父进程或某一子进程close掉套接字时,描述符引用计数会相应的减一,当引用计数仍大于零时,这个close调用就不会引发TCP的四路握手断连过程。
shutdown()函数:
int shutdown(int sockfd,int howto); //返回成功为0,出错为-1.
使用close中止一个连接,但它只是减少描述符的参考数,并不直接关闭连接,只有当描述符的参考数为0时才关闭连接。shutdown可直接关闭描述符,不考虑描述符的参考数,可选择中止一个方向的连接。
(1)shutdown + SHUT_RD:值为0,关闭连接的读这一半
利用shutdown的SHUT_RD参数,可以关闭连接中本段的读,本段不能再从套接字中读数据,而且套接字中接受缓冲区中的数据都将被丢弃,但是对方仍然可以发送数据,只是数据到达本段后都会被悄然丢弃。另外SHUT_RD参数不会对TCP的连接造成任何影响。后面如果再从该套接字调用read会直接返回0。
(2)shutdown+SHUT_WR:值为1,关闭连接的写这一半
SHUT_WR可以关闭连接中本段写的这一半,对于TCP套接字又称为半关闭。当前留在套接字发送缓冲区的数据都被发送掉,后面紧跟TCP的正常连接终止序列。 该选项可以保证在断开连接过程中,本方的数据被对方应用程序收到,具体做法是:
1)调用shutdown + SHUT_WR,此时本方的TCP会把发送缓冲区中的数据发送出去,然后发送FIN序列来正常终止连接。
2)然后调用read,此时read会被阻塞,直到接收到对方发送FIN序列,然后read返回0,因为FIN序列是由对方应用程序调用close或者shutdown产生的,因此可以保证缓冲区中的数据已经被对方应用程序收到。
(3) shutdown+SHUT_RDWR:值为2,连接的读和写都关闭
连接的读半部和写半部都关闭,这与调用shutdown两次等效,第一次调用指定SHUT_RD,第二次调用指定SHUT_WR。
close()和shutdown()函数区别:
1.close函数会关闭套接字ID,如果有其他的进程共享着这个套接字,那么它仍然是打开的,这个连接仍然可以用来读和写,并且有时候这是非常重要的 ,特别是对于多进程并发服务器来说。
2.shutdown会切断进程共享的套接字的所有连接,不管这个套接字的引用计数是否为零,那些试图读得进程将会接收到EOF标识,那些试图写的进程将会检测到SIGPIPE信号,同时可利用shutdown的第二个参数选择断连的方式。