自动重新连接套接字客户端的设计选择

时间:2012-03-30 13:10:34

标签: sockets tcpclient asyncsocket

我正在使用C#中的Windows窗体应用程序。我正在使用一个套接字客户端,它以异步方式连接到服务器。如果连接因任何原因而中断,我希望套接字尝试立即重新连接到服务器。哪个是解决问题的最佳设计?我是否应该构建一个不断检查连接是否丢失并尝试重新连接到服务器的线程?

以下是处理套接字通信的XcomClient类的代码:

        public void StartConnecting()
    {
        socketClient.BeginConnect(this.remoteEP, new AsyncCallback(ConnectCallback), this.socketClient);
    }

    private void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.
            Socket client = (Socket)ar.AsyncState;

            // Complete the connection.
            client.EndConnect(ar);

            // Signal that the connection has been made.
            connectDone.Set();

            StartReceiving();

            NotifyClientStatusSubscribers(true);
        }
        catch(Exception e)
        {
            if (!this.socketClient.Connected)
                StartConnecting();
            else
            { 

            }
        }
    }

    public void StartReceiving()
    {
        StateObject state = new StateObject();
        state.workSocket = this.socketClient;
        socketClient.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(OnDataReceived), state);
    }

    private void OnDataReceived(IAsyncResult ar)
    {
        try
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;

            // Read data from the remote device.
            int iReadBytes = client.EndReceive(ar);
            if (iReadBytes > 0)
            {
                byte[] bytesReceived = new byte[iReadBytes];
                Buffer.BlockCopy(state.buffer, 0, bytesReceived, 0, iReadBytes);
                this.responseList.Enqueue(bytesReceived);
                StartReceiving();
                receiveDone.Set();
            }
            else
            {
                NotifyClientStatusSubscribers(false);
            }
        }
        catch (SocketException e)
        {
            NotifyClientStatusSubscribers(false);
        }
    }

今天我尝试通过检查收到的字节数或捕获套接字异常来捕获断开连接。

1 个答案:

答案 0 :(得分:2)

如果您的应用程序仅接收套接字上的数据,那么在大多数情况下,您将永远不会检测到断开的连接。如果您长时间没有收到任何数据,则无法知道是否因为连接中断或另一端没有发送任何数据。当然,您将以正常方式检测(作为套接字上的EOF)连接以正常方式关闭。

为了检测断开的连接,您需要一个keepalive。你需要:

  • 使另一端保证它将按照设定的时间表发送数据,如果你没有得到它,你就会超时并关闭连接,或
  • 偶尔将探针发送到另一端。在这种情况下,操作系统会注意到连接断开,如果它被破坏,如果它被及时(由对等方重置连接)或最终(连接超时),你将会收到错误。

无论哪种方式,你都需要一个计时器。无论是将事件定时器实现为事件循环中的事件还是作为休眠线程实现,最佳解决方案可能取决于应用程序的其余部分的结构。如果你有一个运行事件循环的主线程,那么它可能最好是挂钩。

您还可以在套接字上启用TCP keepalives选项,但通常认为应用层keepalive更强大。