gpt4 book ai didi

c# - 第二次调用 NetworkStream BeginRead() 大规模资源争用

转载 作者:行者123 更新时间:2023-11-30 21:55:43 24 4
gpt4 key购买 nike

我正在用 TcpClient 编码一个服务器/客户端项目和 NetworkStream对象。我希望许多客户端连接到服务器,这些客户端存储在 List<> 中定制NetworkNode对象,每个对象都有一个 TcpClient和一个 NetworkStream用于与相应客户的沟通。

服务器需要能够保持与客户端的连接,并在接收到消息时立即(快速)等待和操作消息。同步轮询对于这个应用程序来说是非常不受欢迎的,我也不希望以这种方式进行编码。

目前服务器正在异步接受客户端并将它们添加到 List<> ,工作非常顺利。我已经使用控制台应用程序对此进行了测试,该应用程序最多可生成 100 个客户端,并在很短的时间内(< 1 秒)连接到环回地址处的服务器。

当客户端添加到 List<> 时该对象使用 GetStream()方法返回客户端的 NetworkStream目的。我正在尝试使用 NetworkStream.BeginRead()从每个 TCP 客户端实现异步数据接收的方法。对该方法的第一次调用如下:

this.Stream.BeginRead(readBuffer, readBufferOffset, readBuffer.Length - readBufferOffset, 
new AsyncCallback(nodeStreamReadCallback), this.Stream);

因为控制台测试应用程序在连接到服务器后立即发送一些数据,对象的 readCallback(IAsyncResult)方法几乎立即被调用:

private void readCallback(IAsyncResult ar)
{
NetworkStream _stream = (NetworkStream)ar.AsyncState;

int _bytesRead = 0;

_bytesRead = _stream.EndRead(ar);

this.Stream.Write(readBuffer, readBufferOffset, _bytesRead);

//increase buffer offset value
readBufferOffset += _bytesRead;

//TODO process the received data
...

//wait for the next chunk of data
this.Stream.BeginRead(readBuffer, readBufferOffset, readBuffer.Length - readBufferOffset,
new AsyncCallback(readCallback), this.Stream);
}

我正在执行第二次调用 Stream.BeginRead()目的是等待下一个数据 block 到达或变得可用,无论何时何地。

当我注释掉对 Stream.BeginRead() 的第二次调用时一切都运行得非常顺利。所有数据都被接收并发送回每个客户端,没有延迟并且线程使用极少(在此过程中平均使用 2 到 3 个额外的线程)。

但是 - 即使只有一个单个客户端已连接,如果我尝试对 Stream.BeginRead() 进行第二次调用readCallback() 内方法(如上所述) 我遇到了大量 争用问题。对于单个客户端,第二次调用后 CPU 使用率从大约 0% 跃升至 30% 到 60% 之间,线程数可以从 11 跃升至多达 35。

所以这是一个线程或递归问题,我觉得我应该在等待一些事情,但我不能完全理解这里发生的事情。这与我在 TcpListener.BeginAcceptTcpClient() 中使用的模式相同所以我认为它必须以不同的方式运作。

感谢您提供的所有建议,并在此先感谢您的帮助!

最佳答案

检查您的 _bytesRead 是否为 0,因为这意味着您的流已在远程端关闭。再次在这样的流上调用 BeginRead 将导致一次又一次地直接调用您的回调,读取字节数为 0。

关于c# - 第二次调用 NetworkStream BeginRead() 大规模资源争用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32042422/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com