您的位置:首页 > 其它

怎样简单检测socket的健康状态

2013-11-21 17:21 344 查看
载自:http://blog.csdn.net/wmnothing/article/details/7491550

开发程序经常用到socket,新手熟手一般都会用select、recv和send这样几个函数,而且大多数情况下,会用这几个函数也就差不多了。更深入的开发会发现,现成的socket函数并没有提供检测socket是否健康的函数,通常的资料也并没有现成的方法可用。本文提供了一个方案,在windows和linux下初步测试,效果良好。

         必须先声明的是socket通信是双工的(如果读者对此不了解,可先查一下相关资料)。因此socket的健康状态是分两个方向的,一个是你发送(send)的方向,一个是你接收(recv)方向的。只有两个方向都是关闭的,这个socket才是真正关闭的,也只有这两个方向都是健康的,此socket才是真正健康的。真正难以检测的,其实就是这种半健康状态的socket。当然我们也可以认为,如果我们两个方向的状态都可以检测清楚,那么此socket的健康状态我们自然就清楚了。

         好了,先认识一下上面提到的三个函数返回值的含义。
函数名

返回值

select

0 :超时

-1 :socket出错

>0 :有数据已到达

send

0 :发送缓冲区已满

-1 :socket出错

>0 :本次已发送到缓冲区的字节数

recv

0 :对方已主动关闭了此socket

-1 :socket出错

>0 :本次已成功接收的字节数

 

         应该说,你发送(send)方向的健康是由你来控制的,只要你不主动调用close或closesocket,它就是健康的。如果你关闭了这个方向的socket,原则上你一定能记得住,如果实在记不住,getsockname/ getpeername可以帮你检测其状态,它们会返回此socket在本机的IP地址和端口号,如果它们返回-1,那就是你已经主动关闭了这个socket的发送(send)方向。

         麻烦在另一端主动关闭了他的发送(send)方向,而这在你看来是你的接收(recv)方向被关闭了。另一端的这个关闭动作理论上是可以随时发生的,不需要事前通知,也没法事后通知,因此只能由你这一方想办法检测。

         简单地说,当你的接收(recv)方被关闭后,你的select会返回>0的值(这说明对方有数据发送过来),你的recv会返回0(这说明对方已经主动关闭了你的接收recv方向)。这两个值联合起来,说明对方在主动断开后,确实向你这一方发送了数据,但不幸的是,你一接却是个0字节大小。有关socket的几种状态的资料,网上很多,大家可以自己去查。

         上面的方法在通常的实践中就可以使用了,但如果你就想检测socket的接收(recv)方向的状态,就还需要另一个技巧。recv一般是会从缓冲区中拿走数据的,所以当你只想检测状态而又不想拿走数据时,得学会使用recv的第四个参数的用法。通常情况下它是0,但当它为MSG_PEEK时,它的意思是偷看,即看一下缓冲区前面的若干字节,但并不从缓冲区中拿走。在本方案中,只要偷看1个字节就好了,如果返回0,就说明对方已经主动发起关闭了。

 

         我们来总结一下简单地检测socket健康状态的全过程。

         1、用getsockname/ getpeername来检测你的发送(send)方向的状态,如果你不知道你是否主动关闭了这个方向;

         2、用select和recv(,,1,MSG_PEEK)来共同检测你的接收(recv)方向的状态。

 

         特别说明的是,socket的状态其实分好几种,如果你需要详细了解它们的获取方式,欢迎你与我一起探讨。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: