前几天在使用TCP网络编程时在服务器端遇到一个bug,当客户端非正常退出时,服务器也跟着退出。检查了很久也没发现问题在哪,后来去翻看各个函数的实现,发现了send函数的一个隐患点。
在linux下写TCP socket编程时,服务器首先会经历bind,listen去准备好监听套接字,然后accpet客户端的请求,当客户端请求连接服务器时,accpet函数正确返回一个已连接的套接字描述符,之后就会在这个已连接的套接字描述符上和客户端通信; 而在linux下,当我们的程序尝试send数据到一个未连接的套接字描述符上时,就会让底层抛出一个SIGPIPE信号,而对这个信号的缺省处理方式就是退出进程,这样就解释了我最开始提出来的问题发生的原因。当客户端非正常退出后,客户端与服务器之间没有进行正确的四次挥手动作,服务器并不知道这个套接字描述符已经与自己断开了连接,所以仍继续往上面发送数据,之后收到SIGPIPE信号后,由于程序没有对这个信号进行处理,于是系统采用缺省的处理方式,退出进程。由于网络环境的多变性以及客户端健壮性的不确定性,我们不能保证客户端都是正确退出,因此,要解决这个问题,让我们的服务器更加健壮,就要对这个信号进行处理。
解决方法如下,重载这个信号的处理方法,调用以下代码即可安全的屏蔽SIGPIPE
signal(SIGPIPE,SIG_ING);
在main函数中加入这句代码问题就解决啦!