我写socket相关的程序也不是一天两天了,在我的记忆中,只要处理好recv(或read)的返回值中<0,==0,>0三种情况,程序便不会有什么问题。但最近在看公司的源代码时,发现代码中直接将SIGPIPE设置为SIG_IGN。而且附上一段注释:往一个已经关闭的socket写入数据会触发SIGPIPE。我心中顿时一惊,我以前从来没这样做过,虽然没出问题,难道只是我运气好?
周末,决定验证一下。
首先,socket的读事件中,返回0表示socket已关闭。如果已经关闭,再往里面写东西肯定会出问题的,肯定不是这么低级的问题。那么有一种情况,即假如服务端的epoll在一次loop中检测该socket正常,然后去处理其他逻辑。恰好这时客户端这时关闭了socket。接着服务端要往socket写数据。那么,这时是否会出现SIGPIPE呢?于是在网上随便拷贝了几份代码来验证(偷懒...)。
服务端代码

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/socket.h> #include<sys/types.h> #include<unistd.h> #include<netinet/in.h> #include <errno.h> #define PORT 6666 int main(int argc,char **argv) { int ser_sockfd,cli_sockfd; int err,n; struct sockaddr_in ser_addr; struct sockaddr_in cli_addr; char recvline[200]; const char *sendline = "hello client"; ser_sockfd=socket(AF_INET,SOCK_STREAM,0); if(ser_sockfd==-1) { printf("socket error:%s ",strerror(errno)); return -1; } bzero(&ser_addr,sizeof(ser_addr)); ser_addr.sin_family=AF_INET; ser_addr.sin_addr.s_addr=htonl(INADDR_ANY); ser_addr.sin_port=htons(PORT); err=bind(ser_sockfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr)); if(err==-1) { printf("bind error:%s ",strerror(errno)); return -1; } err=listen(ser_sockfd,5); if(err==-1) { printf("listen error "); return -1; } printf("listen the port:%d ",PORT); while(1) { socklen_t addlen=sizeof(struct sockaddr); cli_sockfd=accept(ser_sockfd,(struct sockaddr *)&cli_addr,&addlen); if(cli_sockfd==-1) { printf("accept error "); } while(1) { printf("waiting for client... "); n=recv(cli_sockfd,recvline,1024,0); printf( "recv return %d ",n ); if(n==-1) { printf("recv error "); } recvline[n]='