Socket.Send在第55个调用时停顿约600毫秒

时间:2019-02-24 03:44:18

标签: c# windows networking udpclient

我有一个C#/ WPF应用程序,它每秒30次通过UDP发出一条消息。消息源自自由运行的线程,并被发送到固定的IP地址。根据消息大小,每条消息被分为1-6个数据报,因此我每秒发送30至180个数据报,总吞吐量高达〜250kbps。我一直在追逐一个问题,即我的应用程序的发送速率有时会大大降低。该应用程序是多线程的,除了UI线程外,我还有:

  • 自由运行的后台线程,该线程根据其自身内部时序提供要通过网络发送的数据。这会构造消息数据报,并将它们与目标地址一起添加到ConcurrentQueue
  • 后台发送器线程,它读取ConcurrentQueue并通过Socket.SendTo将数据报发送到所需地址

作为参考,这是套接字初始化:

try
{
    _Socket?.Close();
    _Socket = null;
    _Socket = new Socket(SocketType.Dgram, ProtocolType.Udp);
    _Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    _Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true);
    _Socket.EnableBroadcast = true;

    _Socket.Bind(_LocalEP);
}
catch (SocketException e)
{
    utils.error.SocketExceptionMessage(e, _LocalEP.Address, (UInt16)_LocalEP.Port);
    Stop();
}

经过大量的阴影处理后,我通过检测发送方线程来测量调用花费的时间,从而将行为隔离到Socket.Sendto调用中:

private void SendThreadF()
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    List<long> loopDeltaTs = new List<long>();
    long lastLoopTime=0;

    while (CanSend)
    {
        DGMessage m;
        while (SendQueue.TryDequeue(out m))
        {
            if (CanSend)
            {
                lastLoopTime = sw.ElapsedMilliseconds;
                _Socket.SendTo(m.Datagram, m.Length, SocketFlags.None, m.Destination);
                loopDeltaTs.Add(sw.ElapsedMilliseconds - lastLoopTime);

            }

        }
        Thread.Sleep(10);
    }
    Trace.WriteLine("Send Thread is Exiting!");
}

运行后让应用程序运行一分钟左右,然后中断以检查记录的计时,我看到以下内容:

  • 几乎所有呼叫都需要花费0-1毫秒的时间。
  • 每次第54或55次通话都需要590-598毫秒。
  • 只要线程运行(总共数以万计的样本),此模式似乎就会可靠地重复
  • 相对定时,每隔约600毫秒定期中断,与我在Wireshark中看到的完全匹配

我现在已经两次遇到这种确切的行为,并且每次重新启动计算机后都消失了。

这是一件奇怪的事情:我重新启动计算机,问题停止了。这表明它可能与我的应用程序完全无关,但这仍然会带来用户支持问题。不幸的是,我不知道如何进一步解决此问题。

  • 是否有任何可能由Socket配置引起的方法(尽管我以前使用UdpClient而不是Sockets时就曾遇到此问题)?
  • 是否有已知方法可以使另一个应用程序访问同一端口,从而阻止我的应用程序访问? (FWIW在Wireshark中没有可见的相应流量)
  • 发生此问题时,我还有其他方法可以解决或诊断此问题吗?

0 个答案:

没有答案