Socket与拔掉网线

当客户端与服务端通过Tcp Socket进行通信时,如果客户端应用正常退出或异常退出,服务端都会在对应的连接上获取感知(如返回0、或抛出异常)。但是,如果客户端的网线被拔掉,那么,默认情况下,服务端需要在2个小时后才会感知客户端掉线。对于很多服务端应用程序来说,这么长的反应时间是不能忍受的。
  我们通常在应用层使用“心跳机制”来解决类似的问题,这是可行的。
  然 而,在这里,我们可以使用Socket自己的心跳机制来解决这一问题。 System.Net.Sockets.Socket提供了IOControl()方法给我们来设置Sokect的心跳机制的相关参数。比如,我们设置 KeepAlive的时间为20秒,检查间隔为2秒。可以这样做:


int keepAlive =
-1744830460; // SIO_KEEPALIVE_VALS


byte[] inValue =
new
byte[] { 1, 0, 0, 0, 0x20, 0x4e, 0, 0, 0xd0, 0x07, 0, 0 }; //True, 20 秒, 2 秒

            sock.IOControl(keepAlive, inValue, null);

  20秒(20000毫秒)的16进制表示是4e20,2秒(2000毫秒)的16进制表示是07d0,如此,你可以修改inValue参数为自己希望的值。
  在上述设置下,如果拨掉客户端网线,服务器Socket.Receive()会在20秒后抛出异常(注意,在这20秒服务端内无论是从该
socket上接收消息还是发送消息都不会抛出异常!)。
-----------------------------------
private byte[] KeepAliveTime
        {
            get
            {
                uint dummy = 0;
                byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
                BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
                BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
                BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
                return inOptionValues;
            }
        }
socket.IOControl(IOControlCode.KeepAliveValues, KeepAliveTime, null);

 

你可能感兴趣的:(Socket与拔掉网线)