问题描述:谢了一个客户端和服务端,正常运行后,客户端不断向服务端发送消息,当服务端跟客户端断开连接或者把服务端关闭后,客户端会再发送一次消息后自动退出。而有些情况我们不希望这种情况发生。
原因分析:简单的说就是服务端关闭后,客户端给服务端发送了一条信息,服务端已经关闭,则客户端收到信息,产生SIGPIPE信号,这个信号告诉进程关闭,我们要做的就是捕获这个信号让它按自己的意愿进行
解决方法:
1.signal(SIGPIPE, SIG_IGN):忽略sigpipe信号
2.signal(SIGPIPE, 自己定义的函数名):捕获该信号后可以执行自己定义的函数。下面的例子即采用此方法:
//client.c
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <signal.h>
void signalset()
{printf("signal get\n");getchar();}
int main()
{
int sfp,nfp;
struct sockaddr_in s_add,c_add;
int sin_size;
unsigned short portnum=0x8888;
char buf[1024]="hello server!";
printf("Hello,welcome to my server !\r\n");
sfp = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sfp)
{
printf("socket fail ! \r\n");
return -1;
}
printf("socket ok !\r\n");
bzero(&s_add,sizeof(struct sockaddr_in));
s_add.sin_family=AF_INET;
s_add.sin_addr.s_addr=htonl(INADDR_ANY);
s_add.sin_port=htons(portnum);
if(-1 == connect(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
{
printf("bind fail !\r\n");
return -1;
}
printf("connect ok !\r\n");
signal(SIGPIPE,signalset);
while(1)
{
sleep(2);
if(!send(sfp,buf,sizeof(buf),0)>0)
{
printf("write fail!\r\n");
}
recv(sfp,buf,1024,0);
printf("send:%s\n",buf);
}
close(sfp);
return 0;
}
//server.c
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
int main()
{
int sfp,nfp;
struct sockaddr_in s_add,c_add;
int sin_size;
unsigned short portnum=0x8888;
char buf[1024];
printf("Hello,welcome to my server !\r\n");
sfp = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sfp)
{
printf("socket fail ! \r\n");^M
return -1;
}
printf("socket ok !\r\n");
bzero(&s_add,sizeof(struct sockaddr_in));
s_add.sin_family=AF_INET;
s_add.sin_addr.s_addr=htonl(INADDR_ANY);
s_add.sin_port=htons(portnum);
if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
{
printf("bind fail !\r\n");
return -1;
}
printf("bind ok !\r\n");
if(-1 == listen(sfp,5))
{
printf("listen fail !\r\n");
return -1;
}
printf("listen ok\r\n");
while(1)
{
sin_size = sizeof(struct sockaddr_in);
nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);
if(-1 == nfp)
{
printf("accept fail !\r\n");
return -1;
}
pid_t pid = fork();
if(pid == 0){
while(1){
printf("accept ok!\r\nServer start get connect from :%s",inet_ntoa(c_add.sin_addr));
if(-1 == recv(nfp,buf,1024,0))
{
printf("read fail!\r\n");
return -1;
}
printf("cpuused:%s\n",buf);
}return 0;
}
if(pid > 0)
{
close(nfp);
continue;
}
}
close(sfp);
return 0;
}
只有客户端向服务端发送消息的时候才会发生这种情况,如果不发送那不会自动关闭。另外如果反过来,服务端向客户端发送消息,客户端断开后,服务端应该不会发生这种情况,这里没有验证。如果发生的话也可捕获该信号解决。