linux网络编程之socket十 :shutdown 与 close 函数 的区别 numpy.allclose函数
有时候代码中需要连续多次调用write,可能还来不及调用read得知对方已关闭了连接就被SIGPIPE信号终止掉了,这就需要在初始化时调用sigaction处理SIGPIPE信号,对于这个信号的处理我们通常忽略即可,signal(SIGPIPE, SIG_IGN);如果SIGPIPE信号没有导致进程异常退出(捕捉信号/忽略信号),write返回-1并且errno为EPIPE(Broken pipe)。
#include <unistd.h>
int close(int fd);
close 关闭了自身数据传输的两个方向。
#include <sys/socket.h>
int shutdown(int sockfd, int how);
shutdown 可以选择关闭某个方向或者同时关闭两个方向,shutdown how = 0 or how = 1 or how = 2 (SHUT_RD orSHUT_WR or SHUT_RDWR),后两者可以保证对等方接收到一个EOF字符(即发送了一个FIN段),而不管其他进程是否已经打开了这个套接字。而close不能保证,只有当某个sockfd的引用计数为0,close 才会发送FIN段,否则只是将引用计数减1而已。也就是说只有当所有进程(可能fork多个子进程都打开了这个套接字)都关闭了这个套接字,close 才会发送FIN 段。
所以说,如果是调用shutdown how = 1 ,则意味着往一个已经发送出FIN的套接字中写是允许的,接收到FIN段仅代表对方不再发送数据,但对方还是可以读取数据的,可以让对方可以继续读取缓冲区剩余的数据。
下面使用shutdown 修改客户端程序,在前面讲过的使用select函数修改后的客户端程序基础上,修改很小一部分:
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if(FD_ISSET(fd_stdin,&rset))
{
if(fgets(sendbuf,sizeof(sendbuf),stdin)==NULL)
{
stdineof=1;//表示已经输入完毕
/*关闭sock的写端,还能够接收数据,在sock的发送缓冲区末尾添加一个FIN段*/
shutdown(sock,SHUT_WR);
}
else
{
writen(sock,sendbuf,strlen(sendbuf));
memset(sendbuf,0,sizeof(sendbuf));
}
}
为了测试我们想要的效果,需要在select函数修改后的服务器端程序的 134 行代码之后,即writen 之前 sleep(4); 目的是接收到客户端数据后不马上回射回去,睡眠4s 后在客户端已经关闭连接的情况下再发送数据。
先运行服务器端程序,再运行客户端程序,在客户端标准输入,迅速敲入两行:AAAAAn BBBBBn 然后按下ctrl+d 即fgets 会返回NULL,然后调用shutdown关闭写端,虽然服务器端延时才发送数据,此时客户端写端已经关闭,但还是可以读取到回射回来的数据,服务器端最后得到一个FIN段,read 返回0,打印输出 client close ,并且close(conn); 而客户端在读取服务端回射回来的两次数据后,再次read 也返回0,故打印server connect close,break退出循环,进程顺利退出。从下面的输出还可以看出,因为延时的关系,所以不像以前那样发射一行就回射一行。
simba@ubuntu:~/Documents/code/linux_programming/UNP/socket$ ./echoser_select
recv connect ip=127.0.0.1 port=54010
fdsgfgd
gfedg
client close
...........................
simba@ubuntu:~/Documents/code/linux_programming/UNP/socket$ ./echocli_select_shutdown
local ip=127.0.0.1 port=54010
fdsgfgd
gfedg
fdsgfgd
gfedg
server connect close
如果我们将客户端程序中的shutdown 改成了 close,那么当延时后服务器端发送数据给客户端时,客户端的读端和写端都已经关闭,第一次发AAAAA会返回一个RST段,根据本文前面所说,再次发BBBBB直接产生SIGPIPE信号,默认会终止进程,但因为我们已经设置了忽略SIGPIPE信号,所以服务器端进程不会被终止,但客户端也会出错,因为回到while循环开头,select阻塞等待时发现套接字的读端已经关闭,所以不能再关心可读事件了,select会返回-1,错误码是 EBADF: Bad File Descriptor。
参考:
《Linux C 编程一站式学习》
《TCP/IP详解 卷一》
《UNP》
更多阅读
横穿罗布泊组图之二十:即将在地图上消失的国道惊险翻越阿尔金
横穿罗布泊组图之二十:即将在地图上消失的国道(惊险翻越阿尔金山)赵亚辉摄影/文字整理重要提示:衷心感谢您的关注!近期由于某种技术原因,本文图片可能无法正常浏览。请点击本文人民网镜像链接,即可正常浏览图文。阿尔金山为巨大隆起地
罗立为:我与焦国标的交往……
【罗立为:我与@焦国标的交往……】2014.8.14.与焦国标在北京延庆“四季花海”……(于浩宸摄)那年中秋时分,我到木樨地寓所拜会@康国雄老先生。康老迎门,济济一堂精英,我座位正对着的红夹克先生,康老介绍:“这是焦国标……”分手时
英国系列科幻电视剧《神秘博士》评论之七十:克隆人上
英国系列科幻电视剧《神秘博士》评论之七十:克隆人(上)Tardis一阵抽搐,博士、罗里、潘多来到了一个城堡式的教堂——克隆岛。不知其何年月日。这是《神秘博士》第六季第五集,题为“反叛的肉”。克隆简史种子延续生命的自然克隆方式。一粒
转载 股知道《轮回理论》之四十:故禽兽知用其长,而知者知用其
原文地址:股知道《轮回理论》之四十:故禽兽知用其长,而知者知用其用也。(鬼道子2012-04-1307:55:16)作者:白羽溯雪 踏入市场,必须要五脏俱全,此五脏乃为,认知,心态,思维,技术,趋势。也可以理解为正思维,正见解,正方向的三正原则。踏入市场要懂得
河南大学一百年之六复兴:机遇与挑战并存
之六复兴:机遇与挑战并存1978年2月,国务院发布《关于恢复和办好全国重点高等学校的报告》,河南没有一所学校入选全国重点行列。于是1979年8月,河南省决定开封师范学院改名为河南师范大学,争取尽快达到全国重点大学的水平。1983年,江苏师