日期:2014-05-16  浏览次数:20621 次

关于模拟socket中SIGPIPE信号的问题
我在论坛上看到以下两段话:
“在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。”

1,不过不是很理解,主要是对于“协议传送数据时”和“协议接收数据时”不知道是什么时候?又该如何模拟呢?
2,还有我想分别模拟send和recv产生SIGPIPE,模拟send函数产生SIGPIPE还是很简单的,就对关闭的socket发送两次send,就会产生SIGPIPE,但是如何模拟recv函数产生SIGPIPE呢?


#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <signal.h>

typedef void (*sighandler_t)(int);

void sig_pipe(int signo)
{
printf("捕获到SIGPIPE信号!\n");
}

int main()
{
struct sockaddr_in client_addr;
bzero(&client_addr,sizeof(client_addr));
    
client_addr.sin_family = AF_INET; 
client_addr.sin_addr.s_addr = htons(INADDR_ANY);
client_addr.sin_port = htons(0); 
int client_socket = socket(AF_INET,SOCK_STREAM,0);
if( client_socket < 0)
{
printf("Create Socket Failed!\n");
return(1);
}

struct sockaddr_in server_addr;
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family = AF_INET;
if(inet_aton("189.20.210.137",&server_addr.sin_addr) == 0)
{
printf("Server IP Address Error!\n");
return(1);
}
server_addr.sin_port = htons(6666);
socklen_t server_addr_length = sizeof(server_addr);

if(connect(client_socket,(struct sockaddr*)&server_addr, server_addr_length) < 0)
{
printf("Can Not Connect To 189.20.210.137!\n");
return(1);
}

char buf[1024000];
bzero(buf,sizeof(buf));

int length = 0;

if (signal(SIGPIPE, sig_pipe) == SIG_ERR)
    {
   printf("注册信号函数失败!\n");
   return(1);
    }
 
while (1)
{
do
{
length = recv(client_socket, buf, sizeof(buf), 0);
}
while (length < 0 && errno == EINTR);

if (length < 0) 
{
if (errno  == EAGAIN)
{
printf("EAGAIN\n");
}
}
else if (length == 0)
{
printf("对端主动关闭连接!\n");
//break;
continue;
}
else
printf("from ser: \n%s\n", buf);

//回显给服务器
//send(client_socket, buf, sizeof(buf), 0);

//模拟SIGPIPE信号
//sleep(2);
//send(client_socket, buf, sizeof(buf), 0);
}

close(client_socket);

return 0;
}


------解决方案--------------------
只有“写”才会触发SIGPIPE,recv是不可能的。
Linux内核模块编译、加载&卸载及查看运作结果