假设server和client 已经建立了连接,server调用了close, 发送FIN 段给client(其实不一定会发送FIN段,后面再说),此时server不能再通过socket发送和接收数据,此时client调用read,如果接收到FIN 段会返回0,但client此时还是可以write 给server的,write调用只负责把数据交给TCP发送缓冲区就可以成功返回了,所以不会出错,而server收到数据后应答一个RST段,表示服务器已经不能接收数据,连接重置,client收到RST段后无法立刻通知应用层,只把这个状态保存在TCP协议层。如果client再次调用write发数据给server,由于TCP协议层已经处于RST状态了,因此不会将数据发出,而是发一个SIGPIPE信号给应用层,SIGPIPE信号的缺省处理动作是终止程序。
有时候代码中需要连续多次调用write,可能还来不及调用read得知对方已关闭了连接就被SIGPIPE信号终止掉了,这就需要在初始化时调用sigaction处理SIGPIPE信号,对于这个信号的处理我们通常忽略即可,signal(SIGPIPE, SIG_IGN); 如果SIGPIPE信号没有导致进程异常退出,write返回-1并且errno为EPIPE。
#include <unistd.h> int close(int fd);
close 关闭了自身数据传输的两个方向。
close一个TCP套接字的默认行为是把该套接字标记成已关闭,然后立即返回到调用进程。该套接字描述符不能再由调用进程使用,也就是说它不能作为read或write的第一个参数。然而TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP连接终止序列。
我们可以通过SO_LINGER套接字选项可以用来改变TCO套接字的这种默认行为。
终止网络连接的通常方法是调用close函数。不过close有两个限制,却可以使用shutdown来避免。
(1)close把描述符的引用计数减1,仅在该计数变为0时才关闭套接字。使用shutdown可以不管引用计数就激发TCP的正常连接终止序列。
(2)close终止读和写两个方向的数据传送。既然TCP连接是全双工的,有时候我们需要告知对端我们已经完成了数据发送,即使对端仍然有数据要发送给我们。
#include <sys/socket.h> int shutdown(int sockfd,int howto); 返回:若成功则为0,若出错则为-1
该函数的行为依赖于howto参数的值:
SHUT_RD 关闭连接的读这一半,套接字中不在有数据可接收,而且套接字接收缓冲区中的现有数据都被丢失。进程不能再对这样的套接字调用任何读函数。对一个TCP套接字这样调用shutdown函数后,由该套接字接收的来自对端的任何数据都被确认,然后悄然丢弃。
SHUT_WR 关闭连接的写这一半,对于TCP套接字,这称为半关闭。当前留在套接字发送缓冲区中的数据将被发送掉,后跟TCP的正常连接终止序列。我们已经说过了,不管套接字描述符的引用计数是否等于0,这样的写半部关闭照样执行。进程不能再对这样的套接字调用任何写函数。
SHUT_RDWR 连接的读半部和写半部都关闭,这与调用shutdown两次等效:第一次调用指定SHUT_RD,第二次调用指定SHUT _WR。
作者:csdn博客 ctthuangcheng
查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/OS/unix/
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索数据
, 函数
, 套接字
, 信号
, close
, shutdown
套接字连接已终止
,以便于您获取更多的相关知识。