现在的位置: 首页 > 综合 > 正文

客户端怎么判断Socket连接已与服务器断开

2013年08月09日 ⁄ 综合 ⁄ 共 1818字 ⁄ 字号 评论关闭

First of all , Server's socekt is not close.
if u had closed client's socekt , u should creat it again when u want to connect server's.

socket即使close了,也还是会存在的,除非设置socket的option,设置为立即close
看一下setsockopt()这个函数吧

 

附一朋友的问题:

服务器程序为Socket   Sever,绑定12005端口,启动就Listen,然后客户端不停的连接、断开,在每天4点服务器程序自动关闭后,又由另外一个守候程序打开。服务器运行8-9天后,客户端不能连接了,连接的客户端也请求不了数据,就是说服务器程序不接受SOCKET连接了,发送的数据在OnReceive()不能接受了,在这个时间用远程登录可以登录到服务器,CPU也是4%左右,自己的服务器程序用内存也是不到10M(曾经到过70M也没问题),数据的一条线城也没有堵塞(当时自己打开SQL2000企业管理器查看到的),关闭自己服务器程序,客户端又可以连接上来,但是过了2个小时又是上面的情况,这次关闭自己服务器程序也不能连接了,只好将操作系统关闭,重新启动服务器机器,重起后可以了。  
   
  又要运行到8-9天后才发生重复的事情、、、,好奇怪呀,已经连续发生4次了,找不到原因,  
   
  自己认为  
  1、是不是操作系统的端口8-9天后用完了?如果是  
  2、内存用完了?(1G系统内存,在资源管理器看到是一直稳定到830M左右)  

---------------------------------------------------------------------------------------------------

TCP连接如果不收发数据,大约几十秒之后就会超时,超时之后服务器端不会收到OnClose()  
  这样一来,就会有许多死连接,服务器端无法清除。  
b/S之间没有数据发送的时候要发送一些在线包,比如说,没有数据传输时每20秒发送一个空格  
  Server端对每个连接定时检测,大概象下面这样:  
  OnRecv()  
  {  
    last_recv_time   =   GetTickCount();  
    //do   recv()   here  
  }  
   
  OnTimer()  
  {  
    if(GetTickCount()-last_recv_time>35000)//close   connection   any   way   after   35   seconds'   idle  
    {  
      closesocket(s)  
    }  
  }

客户端要有重连机制

 

 

 

C#中判断socket是否已断开的方法

在C#中,Socket类的Connected属性只表示最后一次I/O操作的状态,如果这之后[连接的另一方]断开了,它还一直返回true, 除非你再通过socket来发送数据。所以通过这个属性来判断是行不通的!
       有人说可以用Socket.Available属性来判断,msdn中说:如果[连接的另一方]断开了,它就会抛出异常。然而,这个BUG报告(http://dam.mellis.org/2004/08/net_socket_bugs_gotchas/)却指出:msdn的说法并不完全正确,这个属性只有在少数情况下才抛出异常。所以,这一招还是行不通!
       事实上,Socket.Receive()方法在[连接的另一方]断开时,它返回结果告知只读了0个字节,我们可以籍由这一点来找出答案。这个问答(http://www.dotnet247.com/247reference/msgs/36/182526.aspx)给出了好的解决方案:可以调用Socket.Poll() 方法,为该方法的第二个参数传入SelectRead 值,如果该方法返回true, 则可以再由Socket.Receive()方法的返回值来判断, 我简要的写出代码:
         Socket s = new Socket(..);
if (s.Poll(-1, SelectMode.SelectRead))
{
   int nRead = s.Receive();
   if (nRead == 0)
   {
     //socket连接已断开
    }
}     
       如果您还有更好的方法,也请告诉我, :).

抱歉!评论已关闭.