在调用close时实际是关闭了减少了文件描述符,当文件描述符引用为0时,则会删除文件,关闭套接字。
shutdown是直接对socket的操作,相当于设置了socket的属性,可以设置为只读,只写,或者直接关闭,但不会操作与此socket相关的文件。
shutdown() doesn’t actually close the file descriptor—it just changes its usability. To free a socket descriptor, you need to use close().
close和shutdown的区别:
close是将套接字的引用减去1,如果调用close之后套接字的引用不为0则什么都不干(也不会发送FIN),当计数等于0时有两种情况,
- 触发TCP/IP的四次挥手,即主动关闭方发送FIN(在未发送的数据全部发送出去后),发完就关闭套接字。
- 丢弃数据直接发送RST
shutdown有三个参数,分别关闭套接字的读端,写端,读写同时关闭,调用shutdown会影响到使用这个套接字的所有进程,shutdown不会操作与socket相关的文件
所以我们在使用套接字时,一般都是先调用shutdown再使用close。
RST报文:
RST标示复位、用来异常的关闭连接。
1. 发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓冲区中的包,发送RST。
2. 而接收端收到RST包后,也不必发送ACK包来确认。
什么时候发送:
前面提到的半打开状态:一个连接的另一端已经关闭,此时发送数据到对端,就会触发RST回包;
到不存在的端口的连接请求:请求连接一个并没有监听的端口,TCP则会返回RST(UDP将会产生一个ICMP端口不可达的信息)。
异常终止一个连接:在关闭连接的时候不是通过FIN报文进行正常关闭,而是通过直接发送RST进行连接关闭。两者的区别:
通过FIN包进行关闭,又称:有序释放(orderly release),因为close()/shutdown()都会将缓冲区中的数据全部发送出去之后,才会发送FIN。
通过RST复位包进行关闭,又称:异常释放(abortive release)。异常释放的特点:
丢弃掉发送缓冲区中的全部数据,立刻发送RST报文;
RST接收方会区分另一端执行的是正常关闭,还是异常关闭。