在一个TCP连接完成后进行通信,如何判断对方已经关闭了?

deeploves 2006-08-14 03:59:19
我accept接收一个连接后进入一个while(1)循环中,如何在这个循环中知道对方关闭或崩溃退出这个死循环到外循环,重新accept?
...全文
532 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
pottichu 2006-08-17
  • 打赏
  • 举报
回复 1
(资本家) 正解!
在对方拔掉网线,或者网络不稳定这种情况,
通过read, recv 都不能检查到 Socket是否已经关闭。
必须发心跳包。
shunek1 2006-08-16
  • 打赏
  • 举报
回复 1
检测连接是否"真正"断开,没有第二条路可走, 客户机和服务器之间必须建立心跳机制, 虽然在read或者write的时候可以判断连接是否"优雅的"断开,但是, 如果直接拔网线或者异常断电等情况的时候,TCP/IP是不会告诉你的, 检测心跳包, 当服务器长时间无法接收心跳包, 可以认定客户端已经死了, 检测心跳的做法也是必需的常规手段.
universes 2006-08-16
  • 打赏
  • 举报
回复 1
呵呵,确实资本家说的才是彻底的解决方法。

我做过一个类似的:
结合资本家说的(我称作keepalive机制)和select,检测对端是否还“存活”

playmud 2006-08-16
  • 打赏
  • 举报
回复
资本家说得好
DanXer 2006-08-15
  • 打赏
  • 举报
回复
答案是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);
}
fytzzh 2006-08-15
  • 打赏
  • 举报
回复
如果对方已经关闭套节子 read write函数返回-1.配合检查errno的值.
同时会收到sigpipe信号.

23,116

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧