确定TCP流是否已断开连接

时间:2013-12-13 01:13:23

标签: c# tcpclient tcplistener tcp-ip networkstream

我处于需要在侦听器和TCPClient之间打开流的情况。流打开后,客户端将发送消息流,我将为每个消息发送一个ACK。如果我在一段时间内没有收到任何消息(默认为5分钟),我将断开与服务器的连接,然后返回监听新连接。

侦听器应该只有一个尝试与之通信的客户端。规范声明应该打开并保持流直到所有消息都已发送,这可能意味着设备连接了几天或更长时间。不幸的是,客户端是第三方软件,我不能保证它不会在每条消息后关闭连接。

我的问题是,如何判断客户端是否已断开连接。我已经完成了我的研究并知道这个问题已经有几个答案了,但是他们基本上说我需要写入流,如果有异常,则连接已经关闭。我编写了代码来执行此操作,但发现某些客户端未设置为处理非ACK的传入消息。到目前为止,我得到的都是记录的错误消息,但我担心这个“ping”可能会导致其中一个客户端崩溃。

我可以在每条消息之后关闭连接,但至少有一个客户端将继续尝试发送一系列中的所有消息,直到它们都在单个流上收到,因此它不适用于此解决方案。

我可以将NetworkStream.ReadTimeout设置为一个小值,例如1秒,但每次超时都会出现异常,并且使用Exceptions进行流量控制并不是很好的代码(尽管我正在做一些它在pinging时)。

下面是我现在所拥有的片段:

while (bytesRead == 0 && isConnected && isListening)
{
    if (stream.CanRead && stream.DataAvailable)
    bytesRead = stream.Read(receivedBytes, 0, BufferSize);
    else
    {
        if (++pingCount % 100 == 0)
        {
            //  Ping the server every 10 seconds to confirm the connection
            pingCount = 0;
            try
            {
                stream.Write(ping, 0, ping.Length);

                //  client.Connected gives the status of the connection at the last communication
                if (!client.Connected)
                    isConnected = false;
            }
            catch (Exception)
            {
                //  If an exception is thrown, then the connection is closed
                isConnected = false;
            }
        }
        Thread.Sleep(100);     //  Wait and try again
    }
}

1 个答案:

答案 0 :(得分:1)

经过一番搜索,我能够找到如何从TcpClient访问Socket。在我这之后,我能够使用民意调查来确认连接仍然是开放的。我的代码如下:

try
{
    if (client.Client.Poll(1000, SelectMode.SelectRead) && client.Client.Available == 0)
    {
        isConnected = false;
    }
}
catch (Exception)
{
    //  If an exception is thrown, then the connection is closed
    isConnected = false;
}

如果连接已关闭,重置,终止,挂起或有可用数据,则Client.Poll返回true。如果您检查Client.Available,并且没有数据,则必须关闭连接。这不是万无一失的,但我的目的是有用的,因为我只是回去听。

此解决方案来自zendar,位于here