2

我有一个应用程序正在监听来自大约 30 辆汽车中调制解调器的消息。我使用 TcpListener 来实现如下所示的服务器代码(省略了错误处理):

...
listener.Start()
...
void 
BeginAcceptTcpClient()
{
    if(listener.Server.IsBound) {
        listener.BeginAcceptTcpClient(TcpClientAccepted, null);
    }
}

void 
TcpClientAccepted(IAsyncResult ar)
{
    var buffer = new byte[bufferSize];

    BeginAcceptTcpClient();
    using(var client = EndAcceptTcpClient(ar)) {
    using(var stream = client.GetStream()) {
        var count   = 0;
        while((count = stream.Read(buffer, total, bufferSize - total)) > 0) {
            total += count;
        }
    }
    DoSomething(buffer)
}

我正确收到消息,我的问题在于断开连接。每 12 小时调制解调器重置并获得一个新的 IP 地址,但服务器继续保持旧连接处于活动状态(它们在 tcpview 中标记为 ESTABLISHED)。有没有办法为旧连接设置超时?我认为通过关闭 TcpClient 来关闭 TCP 连接(这就是在我的本地测试中发生的情况),我做错了什么?

4

1 回答 1

1

实际上,我对代码示例有点困惑——问题表明这些问题的开放时间相当长,但代码对于非常短的突发事件更为典型;对于长时间运行的连接,我希望在这里看到其中一个异步 API,而不是同步 API。

无痕迹地死掉的套接字非常常见,尤其是在与许多都需要发现关闭的中间设备一起分发时。特别是无线网络有时会尝试人为地保持套接字处于活动状态,因为短暂失去无线连接是很常见的,因为设备不希望每次都杀死每个连接。

因此,在连接上实现某种心跳是很常见的,这样您就可以跟踪谁还活着

举个例子——我在这里有一个 websocket 服务器,理论上它可以处理正常关闭(通过指示关闭的特定序列)和不正常的套接字关闭(意外终止连接)——但是我在 19k 连接中看到过去一个小时左右,有 70 人在没有击中任何一个的情况下死亡。因此,相反,我会针对(缓慢的)心跳跟踪活动,如果它们在太长时间后没有响应,则将其杀死。

重新超时;您可以尝试ReceiveTimeout,但这只会在您通常不期望流量有很大差距的情况下对您有所帮助。

于 2012-03-01T12:15:21.190 回答