LoveUnix » 编程开发 & Rational » 检测socket状态的函数
让LU留住您的每

一天 让LU博客留住您的每一天
2003-12-19 09:54 无双
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1--><br />/* See what&#39;s going on with a socket -- is the connection still valid? &nbsp; &nbsp; &nbsp; */<br />int S5IOCheck&#40;S5IOHandle fd&#41; {<br /> &nbsp; &nbsp;struct timeval tv = { 0, 0 };<br /> &nbsp; &nbsp;fd_set rfds, b;<br /> &nbsp; &nbsp;char dummy;<br /> &nbsp; &nbsp;int sv, n;<br /> &nbsp;<br /> &nbsp; &nbsp;FD_ZERO&#40;&amp;b&#41;;<br /> &nbsp; &nbsp;FD_SET&#40;fd, &amp;b&#41;;<br /><br /> &nbsp; &nbsp;S5LogUpdate&#40;S5LogDefaultHandle, S5_LOG_DEBUG&#40;10&#41;, 0, &#34;S5IOCheck&#58; Checking socket status&#34;&#41;;<br /><br /> &nbsp; &nbsp;/* Poll the file descriptor real quick, and see what comes back... &nbsp; &nbsp; &nbsp; */<br /> &nbsp; &nbsp;while &#40;1&#41; {<br />        rfds = b; <br />//使用select来判断<br /> &nbsp; &nbsp; &nbsp; &nbsp;switch &#40;&#40;sv = REAL&#40;select&#41;&#40;fd+1, &amp;rfds, NULL, NULL, &amp;tv&#41;&#41;&#41; {<br /> &nbsp; &nbsp; case 1&#58;<br />//如果激活时<br /> &nbsp; &nbsp; &nbsp; &nbsp; /* Something happened -- either an error or data, ok to recv */<br />使用msg_peer来保留数据在端口中,不影响其它函数的调用<br /> &nbsp; &nbsp; &nbsp; &nbsp; n = RECVSOCKET&#40;fd, &amp;dummy, 1, MSG_PEEK&#41;;<br />//如果是EINTR&#40;收到中断&#41; 那跳过 继续检查<br /> &nbsp; &nbsp; &nbsp; &nbsp; if &#40;n &#60; 0 &amp;&amp; ISSOCKETERROR&#40;EINTR&#41;&#41; continue;<br /> &nbsp;else if &#40;n &#60;= 0&#41; {<br /> &nbsp; &nbsp; &nbsp;S5LogUpdate&#40;S5LogDefaultHandle, S5_LOG_DEBUG&#40;1&#41;, 0, &#34;S5IOCheck&#58; recv failed&#58; %m&#34;&#41;;<br /> &nbsp; &nbsp; &nbsp;return -1;<br /> &nbsp; &nbsp; &nbsp; &nbsp; }<br /> &nbsp; &nbsp; &nbsp; &nbsp; /* fallthrough -- there is real data there... &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/<br /> &nbsp; &nbsp; case 0&#58;<br /> &nbsp; &nbsp; &nbsp; &nbsp; /* Nothing&#39;s happening -- no error, all&#39;s ok. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/<br />如果是0 没有激活 那就不等它了 返回OK<br /> &nbsp; &nbsp; &nbsp; &nbsp; S5LogUpdate&#40;S5LogDefaultHandle, S5_LOG_DEBUG&#40;10&#41;, 0, &#34;S5IOCheck&#58; ok&#34;&#41;;<br /> &nbsp; &nbsp; &nbsp; &nbsp; return sv;<br /> &nbsp; &nbsp; default&#58;<br /> &nbsp; &nbsp; &nbsp; &nbsp; /* Not a valid socket &#40;?&#41;. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */<br />-1 这是肯定出错了 不用想 返回错误<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if &#40;ISSOCKETERROR&#40;EINTR&#41;&#41; continue;<br /> &nbsp; &nbsp; &nbsp; &nbsp; S5LogUpdate&#40;S5LogDefaultHandle, S5_LOG_WARNING, 0, &#34;S5IOCheck&#58; select failed&#58; %m&#34;&#41;;<br /> &nbsp; &nbsp; &nbsp; &nbsp; return -1;<br /> &nbsp; &nbsp; &nbsp; &nbsp;}<br /> &nbsp; &nbsp;}<br />}<br /><!--c2--></div><!--ec2-->

2003-12-19 14:17 ManInBlack
select检测不出如下状况下的socket状态:<br />1、拔网线<br />2、C/S互连状态下,S改变listen socket的监听端口,然后S关闭与C的客户socket(没有用shutdown和closesocket正常关闭),接着C请求与S交互(自然无响应),然后S再恢复listen socket的监听端口为原端口,这时C检测不到当前socket已经无效了。<br /><br />我现在就碰到这样的问题。<br />我的S端被设计成为每一个客户socket开启一个任务线程去处理,这个线程通常可以直接被强制关闭而不释放任何资源,而且这被设计为是合理的情况。因此需要由C端主动检测到自己与S的关联资源是否有效(比如socket),所以就有了我的这些问题。

2003-12-19 17:53 无双
1 是检测不出 一般使用心跳来解决(send时成功 一直到缓冲区满或是超时 recv时接收不到)<br /><br />2 这个问题不懂 你是什么关闭与C的客户SOCKET的 TCP有个序列号 可以进行连接的有效性检测 当你关闭了监听端口再打开时 序列号会重开始<br /><br />另外改变监听端口而不重新开始TCP监听 我想不可能

2003-12-22 14:46 ManInBlack
我没说清楚,再说一遍,问题得实质是:<br />题设:<br />客户机有两个任务TA和TB,TA申请了一个套接字,描述符为FDA,TB申请了一个套接字,描述符为FDB,而且恰好FDB=FDA+1。TA和TB都是外部消息驱动的,也就是只有外部消息到达时,才会触发套接字操作。<br /><br />问题:<br />当由于某种原因,服务器把对应与该客户机的两个套接字FDA和FDB的套接字都关闭掉。然后恰好客户机上TB任务的外部消息先于TA任务到达,于是TA会检测到FDB失效,然后释放该套接字资源并重新申请一个套接字FDB_NEW,结果经过DEBUG发现恰好有FDB_NEW=FDA成立。于是当TA检测FDA时,却没有发现FDA已经失效了(因为实际上此时的FDA就是FDB_NEW),结果TA和TB使用了同一个套接字描述符,造成了会话乱序(因为会话规则建立在一个任务使用一个专有套接字的基础上)。<br /><br />所以,我想问的是:有什么办法可以保证申请到的套接字描述符不是系统曾经分配过的?<br /><br />速回!!

2003-12-22 17:18 无双
每个TCP连接断开后都会有一段时间保留这个套接字<br /><br />这段时间应该是30秒到2分钟吧<br /><br />你可以自己定义自己的数据结构来实现 <br /><br />我想你的问题是关闭SOCKETI时<br />没有关闭与这个SOCKET关联的消息 这应该是一个BUG

2005-8-7 17:36 soulranger
关于心跳设计,以前看书有利用socket带外数据方式传输心跳信号的方法,不过好久没玩,忘记用什么函数做了,那位大侠能贴出来?

2005-8-8 13:22 无双
带外数据就是<br />send时设置最后一个flag<br /><br />不过一般协议中都是使用普通的数据(flag=0)来做心跳的

页: [1]
查看完整版本: 检测socket状态的函数


Powered by Discuz! Archiver 5.5.0  © 2001-2006 Comsenz Inc.