首页 文章

如何在C#中检测套接字断开

提问于
浏览
9

我正在研究一种客户端/服务器关系,它意味着在不确定的时间内来回推送数据 .

我试图克服的问题是在客户端,因为我无法找到一种方法来检测断开连接 .

我在其他人的解决方案中采取了几个传递,从捕获IO异常到轮询所有三个SelectMode上的套接字 . 我还尝试使用轮询的组合,并检查套接字的“可用”字段 .

// Something like this
Boolean IsConnected()
{
    try
    {
        bool part1 = this.Connection.Client.Poll(1000, SelectMode.SelectRead);
        bool part2 = (this.Connection.Client.Available == 0);

        if (part1 & part2)
        {
            // Never Occurs
            //connection is closed
            return false;
        }
        return true;
    }
    catch( IOException e )
    {
        // Never Occurs Either
    }
}

在服务器端,尝试向客户端写入“空”字符(\ 0)会强制执行IO异常,服务器可以检测到客户端已断开连接(非常简单) .

在客户端,相同的操作不会产生异常 .

// Something like this
Boolean IsConnected( )
{
    try
    {

        this.WriteHandle.WriteLine("\0");
        this.WriteHandle.Flush();
        return true;
    }
    catch( IOException e )
    {
        // Never occurs
        this.OnClosed("Yo socket sux");
        return false;
    }
}

我相信我在通过民意调查检测到断开连接时遇到的一个问题是,如果我的服务器自上次检查后还没有向客户端写入任何内容,我可能很容易在SelectRead上遇到错误...确定在这里做什么,我已经追赶了每一个选项来进行我能找到的检测,对我来说没有什么是100%的,最终我的目标是检测服务器(或连接)故障,通知客户端,等待重新连接等等所以我相信你可以想象这是一个不可或缺的部分 .

感谢任何人的建议 . 提前谢谢 .

EDIT: Anyone viewing this question should note the answer below, and my FINAL Comments on it. I've elaborated on how I overcame this problem, but have yet to make a 'Q&A' style post.

1 回答

  • 12

    一种选择是使用TCP保持活动包 . 你通过调用 Socket.IOControl() 打开它们 . 只有恼人的一点是它需要一个字节数组作为输入,所以你必须将你的数据转换成一个字节数组来传入 . 这是一个使用10000ms保持活动并重试1000ms的例子:

    Socket socket; //Make a good socket before calling the rest of the code.
    int size = sizeof(UInt32);
    UInt32 on = 1;
    UInt32 keepAliveInterval = 10000; //Send a packet once every 10 seconds.
    UInt32 retryInterval = 1000; //If no response, resend every second.
    byte[] inArray = new byte[size * 3];
    Array.Copy(BitConverter.GetBytes(on), 0, inArray, 0, size);
    Array.Copy(BitConverter.GetBytes(keepAliveInterval), 0, inArray, size, size);
    Array.Copy(BitConverter.GetBytes(retryInterval), 0, inArray, size * 2, size);
    socket.IOControl(IOControlCode.KeepAliveValues, inArray, null);
    

    只有在您不发送其他数据时才会发送保持活动数据包,因此每次发送数据时,都会重置10000ms计时器 .

相关问题