分类: LINUX
2011-07-14 18:21:21
今天在调试主程序的时候,发现一个问题:当客户端与服务器端连接的情况下,服务器端按ctrl+c是能够正常退出的;但是,直接运行服务器端的程序,不连客户端,然后按ctrl+c就不能退出,必须按ctrl+z挂起后,通过kill掉该进程才能退出。显然这不是正常的退出方法,对程序不利。
简单介绍一下主程序,主程序开了多个线程,其中一个是网络通信的线程net_server_process。经过调试发现原因是:运行服务器端程序的时候,net_server_process线程在accpet那里阻塞,而主程序中ctrl+c后会调用的destroy函数(相当于析构函数),该函数调用pthread_join函数等待net_server_process线程结束,否则就阻塞在那里。这样就导致了上面的情况。
在网上找了一下解决办法:
有人提议用函数间调转函数setjmp和longjmp来实现,这两个函数对于处理发送在深层嵌套函数调用中的出错情况非常有用。具体类似如下:
伪代码如下:
…
#include
…
static jmp_buf jmpbuf;
void sig_exit(int signo);
int main()
{
socket s;
singal(SIGIO, sig_quit);
…
bind(s);
…
if(setjmp(jmpbuf)) {
exit(0);
}
Socket ns = accpet();
}
Sig_exit()
{
Longjmp(jmpbuf, 1);
}
该方法使用了SIGIO可打断阻塞程序的原理,跳出accept阻塞,又利用了longjmp可以跳出函数的原理,彻底摆脱accept的束缚。
本程序如果利用这种方法,调转至另外一个线程,在另外一个线程用pthread_cancel可以强制关闭net_server_process线程,这样子固然可以退出,但是也不是正常退出。所以不推荐。
在这里主要推荐下面这种方法:
其实也很简单,就是在服务器端的destroy函数里判断,服务器端的net线程是否是活的。如果是,则添加一个类似客户端的程序,连一下服务器端,连上了,就马上关闭套接字,这样子net_server_process线程就可以正常退出了。如果实际的客户端连接着,那么按ctrl+c退出的话,destroy函数里面服务器端的net线程肯定已经退出了,所以进程也能正常的退出。从而解决了没有客户端连接的时候不能正常退出的问题。同时有客户端连着的时候,也能正常退出的问题。