免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 32321 | 回复: 12
打印 上一主题 下一主题

socket连接断开后,即刻感知方法讨论。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-11-21 11:24 |只看该作者 |倒序浏览
最近在做一个服务器端程序,C/S结构。功能方面比较简单就是client端与server端建立连接,然后发送消息给server。我在server端会使用专门的线程处理一条socket连接。这就涉及到一个问题,如果socket连接断开(异常,正常)后,我如何才能感知到?server端这边是绝对被动的,sever端不能主动断开连接。也没有连接链路维持包之类的。client端发送数据的时间也是不定的。在socket连接断开后,server要能够感知到并释放资源。
这个问题在思考测试,询问同事之后,找到了一个方法,可以做到这一点。
当使用 select()函数测试一个socket是否可读时,如果select()函数返回值为1,且使用recv()函数读取的数据长度为0 时,就说明该socket已经断开。
为了更好的判定socket是否断开,我判断当recv()返回值小于等于0时,socket连接断开。但是还需要判断 errno是否等于 EINTR 。如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的,socket连接还是正常的,不应close掉socket连接。

PS:对于堵塞socket的recv函数会在以下三种情况下返回:
(1)recv到数据时,会返回。
(2)在整个程序接收到信号时,返回-1。errno = EINTR。//在程序的起始阶段,屏蔽掉信号的除外。部分信号还是屏蔽不掉的。
(3)socket出现问题时,返回-1.具体错误码看 man recv()
(4)一定要看 man 说明,很详细,很有帮助。
这种方法经过长时间测试后,是有效的。所以写出来让大家参考一下,请大家发表意见。

论坛徽章:
0
2 [报告]
发表于 2006-11-21 11:32 |只看该作者
沙发!
我也碰到过这问题,还是用IO复用。

论坛徽章:
39
2017金鸡报晓
日期:2017-02-08 10:39:4219周年集字徽章-周
日期:2023-04-15 12:02:2715-16赛季CBA联赛之深圳
日期:2023-02-16 14:39:0220周年集字徽章-年
日期:2022-08-31 14:25:28黑曼巴
日期:2022-08-17 18:57:0919周年集字徽章-年
日期:2022-04-25 13:02:5920周年集字徽章-20	
日期:2022-03-29 11:10:4620周年集字徽章-年
日期:2022-03-14 22:35:1820周年集字徽章-周	
日期:2022-03-09 12:51:3220周年集字徽章-年
日期:2022-02-10 13:13:4420周年集字徽章-周	
日期:2022-02-03 12:09:4420周年集字徽章-20	
日期:2022-01-25 20:14:27
3 [报告]
发表于 2006-11-21 12:55 |只看该作者
既然server端这边是绝对被动的,那就别管断线的事了,客户端关了你就关,其他不管。

论坛徽章:
0
4 [报告]
发表于 2006-11-21 13:21 |只看该作者
你可以仔细分析下TCP的握手过程,你这种处理也只能判断一些最简单的情况,当然这也是大多数的情况,
UNP 卷一有很多异常情况下模拟解释,你可以看看。另外,网络中间如果有多级路由,路由当掉,等等很多情况,所以才有大多数从应用层加入心跳的做法。

论坛徽章:
0
5 [报告]
发表于 2006-11-21 13:45 |只看该作者
我测试了一下,当我telnet上我的服务器端口,然后关闭telnet窗口的时候,是可以检测到的。
但是当我把自己机器的网线拔掉后,server程序就检测不到了。
在运行程序的服务器上用 netstat 命令查看发现,系统还认为socket连接存在,socket连接的状态还是在“ESTABLISHED”。

我想问一下:操作系统在什么时候才能觉察到socket链路已经断开了?难道是2个小时后?

[ 本帖最后由 UnixPanther 于 2006-11-21 13:50 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2006-11-21 13:48 |只看该作者
原帖由 醉卧水云间 于 2006-11-21 12:55 发表
既然server端这边是绝对被动的,那就别管断线的事了,客户端关了你就关,其他不管。


客户端关闭的时候,是不会给我发任何数据的。服务器端也就感知不到的。
只有检测socket连接是否存在,不过不存在了。就要释放socket。

论坛徽章:
0
7 [报告]
发表于 2006-11-21 16:24 |只看该作者
socket断开用select不是可以检测到可读事件吗?recv返回长度为0不就知道了吗?

论坛徽章:
0
8 [报告]
发表于 2006-11-21 17:46 |只看该作者
原帖由 xwfang 于 2006-11-21 16:24 发表
socket断开用select不是可以检测到可读事件吗?recv返回长度为0不就知道了吗?


是的,这样使可以检测出一部分了。
但是对于网络异常中断的。如:socket连接建立好之后,拔掉client端的网线,这种情况。就不是很容易发现了。而且我还发现操作系统也很难发现这种情况的发生。
我下午就做了这个实验,结果过了4个多小时了。使用netstat命令还是可以看到socket连接,而且连接的状态还是“ESTABLISHED”。我想问的是这种情况下,该如何解决呢?

论坛徽章:
0
9 [报告]
发表于 2006-11-21 17:48 |只看该作者
原帖由 mynets 于 2006-11-21 16:25 发表
TCP protocol has a timer to determine if the connection is abnormally closed. But this timeout value is very long by default and if you want to check this situation as soon as possible to improve p ...


现在就是不想用 链路维持包 。呵呵。

不过终于知道很多协议中为什么要有这个东西了。

论坛徽章:
0
10 [报告]
发表于 2006-11-21 17:52 |只看该作者
隔一段时间server给client发一个消息,询问client"喂,你死了没?",如果client不回复就是挂彩了...也就是说在你的协议中多加这样一条协议.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP