c#中如何探测网络连接是否断开?

来源:互联网 发布:长城宽带独享端口 编辑:程序博客网 时间:2024/06/05 06:23

最近遇到一个问题,linux 的client端改变IP地址后再次连接Windows server端, server不会得到任何连接关闭的通知,用命令:

netstat -anop tcp | find "4114" ,发现连接依然是established状态:

C:\Documents and Settings\riverli>netstat -anop tcp | find "4114"
  TCP    0.0.0.0:4114           0.0.0.0:0              LISTENING       9056
  TCP    172.26.0.99:4114       172.26.0.244:35578     ESTABLISHED     9056

这样如果client端不断地变换IP,那么server端将会有大量的假连接,这是我们不希望看到的。我们希望server也能及时关闭连接释放这些资源。那么如何做呢?

经过google和多方位的实际测试,以下方式是可行的,希望对大家有帮助:

首先需要指定tcp连接的心跳机制,

  tcpServer = new TcpServer(4114);            tcpServer.Connected += new TcpServer.TcpServerEventDlgt(OnConnected);            tcpServer.StartListening();

   void OnConnected(object sender, TcpServerEventArgs e)        {            // Handle the connection here by starting your own worker thread            // that handles communicating with the client.                       try            {              e.ConnectionState.Connection.IOControl(IOControlCode.KeepAliveValues,                              Constants.Constant.KEEPALIVE_VALUES_FB, null);            }            catch (System.Exception ex)            {              log("Exception occurred in setting TCP KeepAlive exp={0}", ex.Message);            }            Thread t = new Thread(new ThreadStart(WorkerThread));            t.Start();        }

其次在线程函数WorkerThread中不断检测socket的状态

    internal void WorkerThread()            {                try                {                    netstream = new NetworkStream(e.ConnectionState.Connection);                    {                                             int nCount = 0;                        while (isRunning && isKeepRunningFromRunCommand)                        {                          nCount++;                          if (nCount == 100)                          {                            nCount = 0;                            if (!e.ConnectionState.isConnected())                              break;                          }                          while (netstream.DataAvailable)                          {                              processIncomingData();                          }                          Thread.Sleep(100);                        }                        log(remoteHost + ": Closing connection");                    }                }                catch (Exception exp)                {                    //an error happened, log it and close the thread                    log("The remote host has disconnected. Exception={0}", getExceptionMessage(exp));
}
e.ConnectionState.Close();

注意看上面的代码,每10 秒钟调用e.ConnectionState.isConnected()去探测一下socket的连接状态,此函数的代码参考msdn,如下:

 // This is how you can determine whether a socket is still connected.        public bool isConnected()        {          bool blockingState = connection.Blocking;          try          {            byte[] tmp = new byte[1];            connection.Blocking = false;            connection.Send(tmp, 0, 0);            return connection.Connected;          }          catch (SocketException e)          {            // 10035 == WSAEWOULDBLOCK            if (e.NativeErrorCode.Equals(10035))            {             //Still Connected, but the Send would block              return true;            }            else            {              //Disconnected: error code {0}!", e.NativeErrorCode);              return false;            }          }          finally          {            connection.Blocking = blockingState;          }        }

connection是Socket类型。
这样如果client端改变IP,几秒钟后调用send函数就会抛出连接关闭的异常。