Socket.SendAsync 需要几秒钟才能完成

2024-01-10

我正在尝试优化 TCP 套接字包装器,该包装器正在处理大量入站连接。我正在一个基本的聊天服务器和一个小型客户端应用程序中测试它,以将客户端发送到它。这两个应用程序都位于通过千兆位交换机连接的单独 W2k3 服务器上。

通过反复试验,我将测试改进为 10 个客户端以 100 毫秒的间隔连接,然后一旦所有 10 个客户端都连接起来,它们都会向服务器发送一条“进入房间”消息,同样以 100 毫秒的间隔。当服务器收到消息时,它会用房间中每个人的列表回复发送者,并向房间中的其他每个人发送一条消息,表示有新消息到达。

每次发送都需要 1 秒多的时间才能完成(对于 100 多个客户端,这个时间会长达 3-4 秒),并且通过日志记录,我已经确定延迟发生在 Socket.SendAync 和引发的相应事件之间。 CPU 使用率始终保持在较低水平。

我已经尝试了我能想到的一切,并花了几天时间在网上寻找线索,但我完全不知所措。这不可能是正常的吧?

编辑:按要求编码。我已经对其进行了一些整理,删除了不相关的计数器和日志记录等,当我试图缩小问题范围时,它目前在黑客之上的黑客之上。

    private void DoSend(AsyncUserToken token, String msg)
    {
        SocketAsyncEventArgs writeEventArgs = new SocketAsyncEventArgs();
        writeEventArgs.Completed += ProcessSend;
        writeEventArgs.UserToken = token;
        Byte[] sendBuffer = Encoding.UTF8.GetBytes(msg + LineTerminator);
        writeEventArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);

        Interlocked.Add(ref m_totalBytesAttemptedSend, sendBuffer.Length);
        Logger2.log(Logger2.Debug5, token.ConnectionId, "Total Bytes attempted: " + m_totalBytesAttemptedSend);

        bool willRaiseEvent = true;
        try
        {
            willRaiseEvent = token.Socket.SendAsync(writeEventArgs);
        }
        catch (Exception e)
        {
            Logger2.log(Logger2.Debug2, token.ConnectionId, e.Message);
            writeEventArgs.Dispose();
        }
        if (!willRaiseEvent)
        {
            ProcessSend(null, writeEventArgs);
        }
    }


    private void ProcessSend(Object sender, SocketAsyncEventArgs e)
    {
        AsyncUserToken token = (AsyncUserToken)e.UserToken;
        Logger2.log(Logger2.Debug5, token.ConnectionId, "Send Complete");
        if (e.SocketError == SocketError.Success)
        {
            Interlocked.Add(ref m_totalBytesSent, e.BytesTransferred);
            Logger2.log(Logger2.Debug5, ((AsyncUserToken)e.UserToken).ConnectionId, "Total Bytes sent: " + m_totalBytesSent);

        }
        else
        {
            if (token.Connected)
            {
                CloseClientSocket(token);
            }
        }
        e.Dispose();
    }

您在每个连接上发送多少数据以及发送速度有多快?

通常异步发送需要很长时间才能完成的原因是您已经填满了 TCP 窗口(请参阅here https://stackoverflow.com/questions/1466307/what-is-a-tcp-window-update详细信息)并且本地 TCP 堆栈无法发送更多数据,直到它从对等方获得一些 ACK。如果您继续发送数据,那么您只是将其在网络子系统中本地排队,因为堆栈不允许发送数据。由于拥塞和数据包丢失,情况可能会变得更糟,因为传输中的数据需要更长的时间才能到达对等点,并且 ACK 需要更长的时间才能返回......

如果是这种情况(并且 WireShark 等工具应该使您能够查看窗口大小更新以及零窗口情况等),那么增加连接的窗口大小可能会有所帮助(请参阅here http://msdn.microsoft.com/en-us/library/ms819736.aspx).

如果您的协议没有明确的流量控制,那么上述情况更有可能发生。恕我直言,最好在协议设计中包含某种形式的显式流量控制来避免这种情况。

包含一些发送端保护也是明智的,因为无限制的发送者可以非常快速地消耗内存。我使用过的一种效果很好的方法是建立一个队列,可以将出站数据放入其中,并且该队列中的数据实际上是根据早期发送的发送完成情况发送的(请参阅here https://stackoverflow.com/questions/3034047/limiting-tcp-sends-with-a-to-be-sent-queue-and-other-design-issues/3036531#3036531).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Socket.SendAsync 需要几秒钟才能完成 的相关文章

  • std::cout 和 std::wcout 有什么区别?

    在c 中 有什么区别std cout and std wcout 它们都控制流缓冲区的输出或将内容打印到控制台 或者它们只是相似吗 它们作用于不同的字符类型 std cout uses char作为字符类型 std wcout uses w
  • 使用Physics.Raycast 和Physics2D.Raycast 检测对象上的点击

    我的场景中有一个空的游戏对象 带有 2D 组件盒碰撞器 我将脚本附加到该游戏对象 void OnMouseDown Debug Log clic 但是当我点击我的游戏对象时 没有任何效果 你有什么想法 如何检测我的盒子碰撞器上的点击 使用光
  • C++ 中本地类中的静态成员变量?

    我知道我们不能宣布static本地类中的成员变量 但其原因尚不清楚 那么请问有人可以解释一下吗 另外 为什么我们不能访问非static函数内部定义的变量 内部已经定义了局部类 直接在局部类成员函数中 在下面给出的代码中 int main i
  • 为 Visual Studio 2013 编译 Tesseract

    我正在尝试使用tesseract在 Visual Studio 2013 中 我在链接器 gt 输入 不是 libtesseract302 static lib 中使用 libtesseract302 lib 一切都正常 并且已编译并运行
  • 如何在 C# 中从 UNIX 纪元时间转换并考虑夏令时?

    我有一个从 unix 纪元时间转换为 NET DateTime 值的函数 public static DateTime FromUnixEpochTime double unixTime DateTime d new DateTime 19
  • 如何为 C 分配的 numpy 数组注册析构函数?

    我想在 C C 中为 numpy 数组分配数字 并将它们作为 numpy 数组传递给 python 我可以做的PyArray SimpleNewFromData http docs scipy org doc numpy reference
  • 互斥体实现可以互换(独立于线程实现)

    所有互斥体实现最终都会调用相同的基本系统 硬件调用吗 这意味着它们可以互换吗 具体来说 如果我使用 gnu parallel算法 使用openmp 并且我想让他们称之为线程安全的类我可以使用boost mutex用于锁定 或者我必须编写自己
  • 单元测试一起运行时失败,单独运行时通过

    所以我的单元测试遇到了一些问题 我不能只是将它们复制并粘贴到这里 但我会尽力而为 问题似乎是 如果我一项一项地运行测试 一切都会按预期进行 但如果我告诉它一起运行测试 则 1 5 将通过 TestMethod public void Obj
  • 如何从 .resx 文件条目获取注释

    资源文件中的字符串有名称 值和注释 The ResXResourceReader类让我可以访问名称和值 有办法看评论吗 你应该能够得到Comment via ResXDataNode class http msdn microsoft co
  • 在 C# 中循环遍历文件文件夹的最简单方法是什么?

    我尝试编写一个程序 使用包含相关文件路径的配置文件来导航本地文件系统 我的问题是 在 C 中执行文件 I O 这将是从桌面应用程序到服务器并返回 和文件系统导航时使用的最佳实践是什么 我知道如何谷歌 并且找到了几种解决方案 但我想知道各种功
  • C# Dns.GetHostEntry 不返回连接到 WiFi 的移动设备的名称

    我有一个 C 中的 Windows 窗体应用程序 我试图获取列表中所有客户端的主机名 下面给出的是 ra00l 来自此链接的代码示例 GetHostEntry 非常慢 https stackoverflow com questions 99
  • 关于在 Windows 上使用 WiFi Direct Api?

    我目前正在开发一个应用程序 我需要在其中创建链接 阅读 无线网络连接 在桌面应用程序 在 Windows 10 上 和平板电脑 Android 但无关紧要 之间 工作流程 按钮 gt 如果需要提升权限 gt 创建类似托管网络的 WiFi 网
  • 未经许可更改内存值

    我有一个二维数组 当我第一次打印数组的数据时 日期打印正确 但其他时候 array last i 的数据从 i 0 到 last 1 显然是一个逻辑错误 但我不明白原因 因为我复制并粘贴了 for 语句 那么 C 更改数据吗 I use g
  • 如何将自定义 JSON 文件添加到 IConfiguration 中?

    我正在使用 asp net Autofac 我正在尝试加载自定义 JSON 配置文件 并基于该文件创建 实例化 IConfiguration 实例 或者至少将我的文件包含到默认情况下构建的 IConfiguration asp net 中
  • 如何使用 Mongodb C# 驱动程序连接多个集合

    我需要将 3 个集合与多个集合合并在一起 lookup我在 C 驱动程序中尝试过 它允许我 lookup用户采集但无法执行秒 lookup用于设置集合 有人可以帮忙吗 db Transactions aggregate lookup fro
  • 将 log4net 与 Autofac 结合使用

    我正在尝试将 log4net 与 Autofac 一起使用 我粘贴了这段代码http autofac readthedocs org en latest examples log4net html http autofac readthed
  • HttpWebRequest 在第二次调用时超时

    为什么以下代码在第二次 及后续 运行时超时 代码挂在 using Stream objStream request GetResponse GetResponseStream 然后引发 WebException 表示请求已超时 我已经尝试过
  • 如何在 C# 中调整图像大小同时保持高质量?

    我从这里找到了一篇关于图像处理的文章 http www switchonthecode com tutorials csharp tutorial image editing saving cropping and resizing htt
  • 使用 GhostScript.NET 打印 PDF DPI 打印问题

    我在用GhostScript NET http ghostscriptnet codeplex com打印 PDF 当我以 96DPI 打印时 PDF 打印效果很好 但有点模糊 如果我尝试以 600DPI 打印文档 打印的页面会被极大地放大
  • 如何正确使用 std::condition_variable?

    我很困惑conditions variables以及如何 安全 使用它们 在我的应用程序中 我有一个创建 gui 线程的类 但是当 gui 是由 gui 线程构造时 主线程需要等待 情况与下面的函数相同 主线程创建互斥体 锁和conditi

随机推荐