当前位置: 技术问答>linux和unix
在一个TCP连接完成后进行通信,如何判断对方已经关闭了?
来源: 互联网 发布时间:2015-12-10
本文导语: 我accept接收一个连接后进入一个while(1)循环中,如何在这个循环中知道对方关闭或崩溃退出这个死循环到外循环,重新accept? | 如果对方已经关闭套节子 read write函数返回-1.配合检查errno的值....
我accept接收一个连接后进入一个while(1)循环中,如何在这个循环中知道对方关闭或崩溃退出这个死循环到外循环,重新accept?
|
如果对方已经关闭套节子 read write函数返回-1.配合检查errno的值.
同时会收到sigpipe信号.
同时会收到sigpipe信号.
|
答案是select 或pselect 调用。
这是发送,看socket是否可以发送,可以则发送,不可以则尝试直到ntimeout秒后。
fd_set wfds;
FD_ZERO(&wfds);
FD_SET(socket,&wfds);
struct timeval tmout;
tmout.tv_sec=ntimeout;
tmout.tv_usec=0;
int nselect=select(1024,NULL,&wfds,NULL,&tmout);
if(nselect==-1)
{
//select调用错误,报告错误,一般通过errno
}
else if(nselect)
{
//可写进行发送(网络物理和传输链路OK)
int sret;
sret=send(socket,....);
if(sret==-1){
//Send出错,检查或报告错误,一般通过errno
}
}
else
{
//不可写,连接问题,检查或报告错误,一般通过errno
shutdown(socket,SHUT_RDWR);
close(socket);
}
这是接收部分,同发送过程基本相同,除了rfds的位置。
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(socket,&rfds);
struct timeval tmout;
tmout.tv_sec=ntimeout;
tmout.tv_usec=0;
int nselect=select(1024,&rfds,NULL,NULL,&tmout);
if(nselect==-1)
{
//select调用错误,报告错误,一般通过errno
}
else if(nselect)
{
//可读,进行接收(网络物理和传输链路OK,且有income数据)
int sret;
sret=recv(socket,....);
if(sret==-1){
//recv出错,检查或报告错误,一般通过errno
}
}
else
{
//不可读,连接问题或无数据可读,检查或报告错误,一般通过errno
shutdown(socket,SHUT_RDWR);
close(socket);
}
这是发送,看socket是否可以发送,可以则发送,不可以则尝试直到ntimeout秒后。
fd_set wfds;
FD_ZERO(&wfds);
FD_SET(socket,&wfds);
struct timeval tmout;
tmout.tv_sec=ntimeout;
tmout.tv_usec=0;
int nselect=select(1024,NULL,&wfds,NULL,&tmout);
if(nselect==-1)
{
//select调用错误,报告错误,一般通过errno
}
else if(nselect)
{
//可写进行发送(网络物理和传输链路OK)
int sret;
sret=send(socket,....);
if(sret==-1){
//Send出错,检查或报告错误,一般通过errno
}
}
else
{
//不可写,连接问题,检查或报告错误,一般通过errno
shutdown(socket,SHUT_RDWR);
close(socket);
}
这是接收部分,同发送过程基本相同,除了rfds的位置。
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(socket,&rfds);
struct timeval tmout;
tmout.tv_sec=ntimeout;
tmout.tv_usec=0;
int nselect=select(1024,&rfds,NULL,NULL,&tmout);
if(nselect==-1)
{
//select调用错误,报告错误,一般通过errno
}
else if(nselect)
{
//可读,进行接收(网络物理和传输链路OK,且有income数据)
int sret;
sret=recv(socket,....);
if(sret==-1){
//recv出错,检查或报告错误,一般通过errno
}
}
else
{
//不可读,连接问题或无数据可读,检查或报告错误,一般通过errno
shutdown(socket,SHUT_RDWR);
close(socket);
}
|
检测连接是否"真正"断开,没有第二条路可走, 客户机和服务器之间必须建立心跳机制, 虽然在read或者write的时候可以判断连接是否"优雅的"断开,但是, 如果直接拔网线或者异常断电等情况的时候,TCP/IP是不会告诉你的, 检测心跳包, 当服务器长时间无法接收心跳包, 可以认定客户端已经死了, 检测心跳的做法也是必需的常规手段.
|
呵呵,确实资本家说的才是彻底的解决方法。
我做过一个类似的:
结合资本家说的(我称作keepalive机制)和select,检测对端是否还“存活”
我做过一个类似的:
结合资本家说的(我称作keepalive机制)和select,检测对端是否还“存活”