【问题标题】:Determining whether an TCP stream has been disconnected确定 TCP 流是否已断开连接
【发布时间】:2013-12-31 16:27:50
【问题描述】:

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

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

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

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

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

下面是我现在拥有的sn-p:

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
    }
}

【问题讨论】:

  • 这听起来是一场灾难。如果你不能就这些非常基本的事情达成一致,那么你将有一段时间让它发挥作用。写一个规范,让它变得艰难。
  • 我同意如果我们能做到这一点会容易得多,但我们正在与几个不同的预先存在的客户合作,并且需要尽可能通用,因为我们不知道什么软件将发送消息,仅发送消息内容。

标签: c# tcpclient tcplistener tcp-ip networkstream


【解决方案1】:

经过一番搜索,我找到了如何从 TcpClient 访问 Socket。完成此操作后,我可以使用 Poll 确认连接仍处于打开状态。我的代码如下:

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

【讨论】:

    猜你喜欢
    • 2012-02-12
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    相关资源
    最近更新 更多