终止tcp网络连接的几种方式
- 调用close
- 调用shutdown
- 进程退出(调用exit或从main函数返回,或收到一个终止本进程的信号)
close()函数
调用close函数可以产生以下效果:
- 导致相应socket套接字的引用计数减一。如果引用计数为0时,发送FIN包。
- 指明本进程不应该再使用对应的socket套接字。
对于单进程而言,因为其socket套接字的引用计数不会超过1,因此调用close就直接激发挥手了。
close()函数的作用是双向的,也就是说,网络连接的两端只要有一端调用了close(),那么这个连接两端都没办法对该网络连接进行读写。
如果对端调用了close(), 则本进程调用read和write的反应分别如下所示:
- read: read返回0,(收到FIN包)
- write:第一次write会把数据发送到对方缓冲区(write返回值是ok的,发送的报文会得到ACK应答),但会收到对端发送的RST报文。第二次调用的话会直接产生SIG_PIPE信号,导致进程崩溃(一般要屏蔽该信号)。
对于本端调用close(),则不应该再使用对应的socket套接字,因而不讨论read和write的结果。
shutdown()函数
#include <sys/socket.h>
int shutdown(int sockfd, int how);
- shutdown()函数允许单向地关闭网络连接。
- shutdown()不关注引用计数,不会被引用技术限制其行为。
参数how取值如下:
- SHUT_RD: 关闭连接的读,不会发送FIN包。
- SHUT_WR: 关闭连接写, 发送FIN报文。
- SHUT_RDWR: 关闭连接读和写
小结
- socket函数都是作用于自身内核的,不能直接改变对端的TCP状态。(对端只有在收到报文后才能)
- 如果进行不再对套接自进行写(调用close或shutdown–SHUT_WR/SHUT_RDWR),则内核会向对方发送FIN包。