TCP客户端退出,服务器自动退出问题

TCP客户端退出,服务器自动退出问题

基于C/S架构的简单 server和client 程序存在一个问题:当客户端退出,关闭套接字时,服务器程序会继续向一个已关闭的套接字发送数据,这时内核会发送 SIGPIPE 信号給应用程序,而应用程序对这个信号的默认处理方式是杀掉进程,最终导致服务器程序也退出。

解决办法:使用send 函数,其参数最后一个用 MSG_NOSIGNAL 让SIGPIPE不影响send函数;
但是,send 函数向一个已经关闭的套接字写数据,其返回值为 -1;
那么,有了这个返回值,就可以自己处理客户端关闭套接字的问题了。

部分代码:

server.c

#include <signal.h>
/套接字初始化程序************/
int init_server(u_short port, int backlog)
{
int s = socket(AF_INET, SOCK_STREAM, 0); //创建流式套接字 主动套接字
if(0 > s){
perror(“socket”);
return -1;
}
struct sockaddr_in addr = { //地址结构
.sin_family = AF_INET, //IPv4
.sin_port = htons(port), //端口(转换成网络字节序)
.sin_addr = {
.s_addr = INADDR_ANY, //ip:本地路由
},
.sin_zero = {0}, //保留
};
socklen_t len = sizeof(addr); //地址结构的长度

if(0 > bind(s, (struct sockaddr *)&addr, len)){		//绑定IP和端口
	perror("bind");
	goto ERR_STEP;
}

	if(0 > listen(s, backlog)){		//设置监听数     转化为监听套接字,供服务器使用
	perror("listen");
	goto ERR_STEP;
}

	return s;	//返回监听套接字

ERR_STEP: //错误处理段(集中报错)
close(s);
return -1;
}

/TCP线程主程序*************/
void * TCP_main(void*arg)
{

int s = init_server(59999, 10);			//得到监听套接字
if(0 > s){
	return -1;
}

printf("wait for a client\n");

struct sockaddr_in addr;
socklen_t len = sizeof(addr);

START_SERVER:
printf("---------------------wait client connect---------------------------\n");
int rws = accept(s, (struct sockaddr *)&addr, &len); //等待连接 创建读写套接字
if(0 > rws){
perror(“accept”);
return;
}

//打印客户端的IP和端口
printf("-----------------Client : [%s:%d] connected !--------------------\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

while(1)
{

		//数据收发
		int num = send(rws,TCP_send_buffer,TCPbuf_len,MSG_NOSIGNAL);	//此处用于跳转回等待连接
		if(num < 0)
		{
			printf("------ Client leave ! close socket ------\n");
			close(rws);
			goto START_SERVER;
		
		}
		memset(TCP_send_buffer, 0, TCPbuf_len); 
}

close(rws);
close(s);
return;
}

pthread_t TCP_send_thread(void) //线程创建函数
{

pthread_t TCP_send_tid;
if(pthread_create(&TCP_send_tid, NULL, TCP_main, NULL))
{
	printf("TCP_send_thread create error!\n");
	return -1;
}else
{
	printf("TCP_send_thread create OK!\n");
}
return TCP_send_tid;

}

END********************
另外 signal(SIGPIPE, sig_handler); 可以捕捉到SIGPIPE信号,但是我没有实现跳转,不能让服务器跳转到等待连接的状态,,,欢迎指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值