我写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\n",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\n",strerror(errno));  
        return -1;  
    }  
      
    err=listen(ser_sockfd,5);  
    if(err==-1)  
    {  
        printf("listen error\n");  
        return -1;  
    }  
      
    printf("listen the port:%d\n",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\n");  
        }  
        while(1)  
        {  
            printf("waiting for client...\n");  
            n=recv(cli_sockfd,recvline,1024,0);
            printf( "recv return %d\n",n ); 
            if(n==-1)  
            {  
                printf("recv error\n");  
            }  
            recvline[n]='\0';  
              
            printf("recv data is:%s\n",recvline);  
              
            int ret = send(cli_sockfd,sendline,strlen(sendline),0);  
            printf( "send return %d\n",ret );
        }  
        close(cli_sockfd);  
    }  
      
    close(ser_sockfd);  
      
    return 0;  
} 
View Code

相关文章: