我处于需要在侦听器和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
}
}
答案 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。