socket close()和shutdown()区别

2016-08-05  本文已影响2615人  dacheng

shutdown() doesn't actually close the file descriptor—it just changes its usability. To free a socket descriptor, you need to use close().

以下均基于单进程socket。

服务端调用shutdown()

服务端调用close()

通过参数设置不同,调用close会出现如下A,B两种情况:

A. 向客户端发送一个RST报文,丢弃本地缓冲区的未读数据,关闭socket并释放相关资源,此种方式为强制关闭。(l_onoff为非0,l_linger为0,)

B. 向客户端发送一个FIN报文,收到client端FIN ACK后,进入了FIN_WAIT_2阶段,可参考TCP四次挥手过程,此种方式为优雅关闭。如果在l_linger的时间内仍未完成四次挥手,则强制关闭。( l_onoff 为非0,l_linger为非0)

FIN与RST

(注意所有FIN及ACK报文均由操作系统自动完成发送接收)

server发送RST报文后,并不等待从client端接收任何ack响应,直接关闭socket。而client端收到RST报文后,也不会产生任何响应。client端收到RST报文后,程序行为如下:

  1. 阻塞模型下,内核无法主动通知应用层出错,只有应用层主动调用read()或者write()这样的IO系统调用时,内核才会利用出错来通知应用层对端已经发送RST报文。
  2. 非阻塞模型下,select或者epoll会返回sockfd可读,应用层对其进行读取时,read()会报RST错误。

通过read write函数出错返回后,获取errno来确定对端是否发送RST信号。

client端收到RST信号后,如果调用read函数读取,则会返回RST错误。在已经产生RST错误的情况下,继续调用write,则会发生epipe错误。此时内核将向客户进程发送 SIGPIPE 信号,该信号默认会使进程终止,通常程序会异常退出(未处理SIGPIPE信号的情况下)。

在收到server发送RST报文的情况下,client端的任何read write都是毫无意义的。

上一篇 下一篇

猜你喜欢

热点阅读