自动重连socket客户端的设计选择

Posted

技术标签:

【中文标题】自动重连socket客户端的设计选择【英文标题】:Design choice for automatically reconnecting socket client 【发布时间】:2012-03-30 13:10:34 【问题描述】:

我正在使用 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】:

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

为了检测断开的连接,您需要保持连接。您需要:

让另一端保证它会按设定的时间表发送数据,如果你没有收到,你会超时并关闭连接,或者, 不时向另一端发送一次探测。在这种情况下,操作系统会注意发现连接断开,如果连接断开,您将在读取套接字时收到错误消息,无论是立即(由对等方重置连接)还是最终(连接超时)。

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

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

【讨论】:

以上是关于自动重连socket客户端的设计选择的主要内容,如果未能解决你的问题,请参考以下文章

MQTT 客户端自动重连机制

【tcp】 TCP的连接重连&QUIC的连接迁移

socket 用disconnect 断开,再重新连接怎么搞

nodejs socket 怎么检测客户端主动断开连接

hpsocket默认心跳

socket编程中为啥client端的可以不用bind函数绑定.而客户端必须呢?