为什么TcpListener会泄漏ESTABLISHED连接?

时间:2012-03-01 11:58:46

标签: c# asyncsocket tcplistener tcp-ip disconnection

我有一个应用程序,它从大约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连接已关闭(这就是我本地测试中发生的事情),我做错了什么?

1 个答案:

答案 0 :(得分:1)

我实际上对代码示例感到有些困惑 - 问题建议这些问题开放的时间相当长,但代码在非常短的时间内更为典型;对于长时间运行的连接,我希望在这里看到一个异步API,而不是同步API。

没有跟踪而死的套接字是非常常见的,特别是当与许多中间设备一起分发时,这些设备都需要发现关闭。特别是无线网络有时会试图使套接字人为地保持活跃,因为短暂地失去无线连接是很常见的,因为设备不希望每次都杀死每个连接。

因此,在连接上实现某种心跳是很常见的,这样你就可以跟踪谁仍然真正活着。

作为一个例子 - 我在这里有一个websocket服务器,理论上处理正常关闭(通过指示闭包的特定序列)和非正常的套接字闭包(意外地终止连接) - 但是在我过去一小时左右看到的19k连接中,有70个已经死亡而没有击中其中任何一个。因此,我会跟踪(缓慢)心跳的活动,如果长时间没有响应就会杀死它们。

重新超时;您可以尝试使用ReceiveTimeout,但如果您通常不希望流量存在较大差距,那么这只会对您有所帮助。