如何在 C# 中检测套接字断开连接 [英] How to detect a Socket Disconnect in C#

查看:41
本文介绍了如何在 C# 中检测套接字断开连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一种客户端/服务器关系,旨在在不确定的时间内来回推送数据.

I'm working on a client/server relationship that is meant to push data back and forth for an indeterminate amount of time.

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

The problem I'm attempting to overcome is on the client side, being that I cannot manage to find a way to detect a disconnect.

我已经对其他人的解决方案进行了几次尝试,范围从仅捕获 IO 异常到轮询所有三个 SelectMode 上的套接字.我还尝试结合使用轮询,并检查套接字的可用"字段.

I've taken a couple of passes at other peoples solutions, ranging from just catching IO Exceptions, to polling the socket on all three SelectModes. I've also tried using a combination of a poll, with a check on the 'Available' field of the socket.

// 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 异常,并且服务器可以检测到客户端已断开连接(非常简单的演出).

On the server side, an attempt to write an 'empty' character ( \0 ) to the client forces an IO Exception and the server can detect that the client has disconnected ( pretty easy gig ).

在客户端,同样的操作也不例外.

On the client side, the same operation yields no exception.

// 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% 的,最终我的目标是检测服务器(或连接)故障,通知客户端,等待重新连接等.所以我相信你可以想象这是一个不可或缺的部分.

A problem that I believe I am having in detecting a disconnect via a poll, is that I can fairly easily encounter a false on a SelectRead, if my server hasn't yet written anything back to the client since the last check... Not sure what to do here, I've chased down every option to make this detection that I can find and nothing has been 100% for me, and ultimately my goal here is to detect a server (or connection) failure, inform the client, wait to reconnect, etc. So I am sure you can imagine that this is an integral piece.

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

Appreciate anyone's suggestions. Thanks ahead of time.

查看此问题的任何人都应注意下面的答案,以及我对此的最终评论.我已经详细说明了我是如何克服这个问题的,但还没有发表问答"风格的帖子.

推荐答案

一种选择是使用 TCP 保持活动数据包.您可以通过调用 Socket.IOControl() 来打开它们.唯一令人讨厌的是它需要一个字节数组作为输入,因此您必须将数据转换为一个字节数组才能传入.这是一个使用 10000 毫秒保持活动并重试 1000 毫秒的示例:

One option is to use TCP keep alive packets. You turn them on with a call to Socket.IOControl(). Only annoying bit is that it takes a byte array as input, so you have to convert your data to an array of bytes to pass in. Here's an example using a 10000ms keep alive with a 1000ms retry:

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);

仅当您不发送其他数据时才会发送保持活动数据包,因此每次发送数据时,10000 毫秒计时器都会重置.

Keep alive packets are sent only when you aren't sending other data, so every time you send data, the 10000ms timer is reset.

这篇关于如何在 C# 中检测套接字断开连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆