Socket连接关闭后产生了大量的FIN_WAIT_1

effun 2014-09-23 03:35:19
一个数据转发服务,运行在服务器R上,从远端服务器S接收数据后,转发到内网中的另一台服务器T上。当S和R建立连接后,R和S建立连接,如果有一方断开连接,另一方自动断开。在运行期间,R和S会因为各种原因不定期断开的情况,断开后S会自动重连到S。

现在的问题是,当运行一段时间以后,大约1个多月吧,在R上用netstat查看,会有大量的FIN_WAIT_1连接存在,大约300多条。由于R到T是经过一台防火墙,从防火墙上看这些连接还是处于已连接的状态。

对Socket不是太了解,请教大牛这是怎么回事。我在程序里用的是TcpClient,关闭连接的代码如下:


public void Close()
{
_isDisposing = true;
if (_tcpClient.Connected)
_tcpClient.Close();
_isDisposing = false;
}


...全文
1009 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
不馁的心 2017-06-13
  • 打赏
  • 举报
回复
设定SO_LINGER选项可以解决这个问题 linger sLinger; sLinger.l_onoff = 1; // ( 在closesocket()调用,但是还有数据没发送完毕的时候容许逗留) sLinger.l_linger = 0; // ( 容许逗留的时间为0秒) setsockopt(hSocket,SOL_SOCKET,SO_LINGER,(char*)&sLinger,sizeof(linger));
xdashewan 2014-09-24
  • 打赏
  • 举报
回复
引用 6 楼 effun 的回复:
有没有可能和中间的防火墙有关?
这是通信关闭时的4次握手,按照你的说法,R是你写的,那么s断开连接你应该可以检测到,那么r和t之间的连接应当由你来切断,当然考虑到s会发起重联,那么肯定有个超时机制。至于你netstat看到的FIN_WAIT_1,你得确定发送方和接收方,然后再去找没有发送fin/ack的原因
effun 2014-09-24
  • 打赏
  • 举报
回复
引用 2 楼 bdmh 的回复:
也可能是没有执行close,或者对方没有应答,客户端接收不到对方同意关闭的信号
有没有可能和中间的防火墙有关?
effun 2014-09-24
  • 打赏
  • 举报
回复
引用 3 楼 rtdb 的回复:
〉 如果有一方断开连接,另一方自动断开。 实际上是做不到的,有时跟本收不到断开连接的信号, 一般需要超时检查,或定期发心跳包才能发现网络已断了。
下面是接收数据和检测连接断开的代码

private void MainLoop()
{
    NetworkStream stream = _tcpClient.GetStream();
    byte[] buffer = new byte[BUFFER_SIZE];

    while (stream.CanRead)
    {
        int received;
        try
        {
            received = stream.Read(buffer, 0, BUFFER_SIZE);
        }
        catch (SocketException)
        {
            break;
        }
        catch (System.IO.IOException)
        {
            break;
        }
        if (received == 0)
        {
            break;
        }
        else if (!_isDisposing)
        {
            byte[] data = new byte[received];
            Array.Copy(buffer, data, received);
            _dataArrivedCallback(this, data);
        }
    }
    _closedCallback(this);
    Console.WriteLine("Disconnected from " + _endPoint.Address);
}
已经尽可能考虑到断开连接可能发生的情况,捕捉断开应该是没有问题的。另外,S和T上都不是我写的程序,也没办法改,我的程序只做数据转发,要增加心跳的功能不太现实。 我查了一些Socket的资料,说服务端打算断开连接时向客户端发送一个FIN包后随即进入FIN_WAIT_1状态,等到客户反馈的FIN/ACK包后,转入FIN_WAIT_2。 由于SR的连接被S断开的情况比较多,所以我认为SR断开的情况是已经检测到了,而问题在于RT的Socket没有断开,在R上没有收到T反馈的FIN/ACK。
effun 2014-09-24
  • 打赏
  • 举报
回复
引用 3 楼 rtdb 的回复:
问题里你这个最重要的RST写错了太多次 。。。
果然写错了,呵呵,更正如下: 当S和R建立连接后,R和T建立连接,如果有一方断开连接,另一方自动断开。在运行期间,R和S会因为各种原因不定期断开的情况,断开后S会自动重连到R。
rtdb 2014-09-24
  • 打赏
  • 举报
回复
问题里你这个最重要的RST写错了太多次 。。。 〉 如果有一方断开连接,另一方自动断开。 实际上是做不到的,有时跟本收不到断开连接的信号, 一般需要超时检查,或定期发心跳包才能发现网络已断了。
bdmh 2014-09-24
  • 打赏
  • 举报
回复
也可能是没有执行close,或者对方没有应答,客户端接收不到对方同意关闭的信号
effun 2014-09-24
  • 打赏
  • 举报
回复
自己顶一下,没人会吗?
effun 2014-09-24
  • 打赏
  • 举报
回复
引用 7 楼 xdashewan 的回复:
[quote=引用 6 楼 effun 的回复:] 有没有可能和中间的防火墙有关?
这是通信关闭时的4次握手,按照你的说法,R是你写的,那么s断开连接你应该可以检测到,那么r和t之间的连接应当由你来切断,当然考虑到s会发起重联,那么肯定有个超时机制。至于你netstat看到的FIN_WAIT_1,你得确定发送方和接收方,然后再去找没有发送fin/ack的原因[/quote] 今天发现所有的FIN_WAIT_1全部没有了,等出现再去看看,谢谢。

110,535

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧