gpt4 book ai didi

c# - 处理异步时的 TcpClient 与 Socket

转载 作者:IT王子 更新时间:2023-10-29 04:31:03 25 4
gpt4 key购买 nike

这不是另一个 TcpClient vs Socket。

TcpClient 是 Socket 类的包装器,以简化开发,同时也暴露了底层的 Socket。

还是...

在 TcpClient 类的 MSDN 库页面上,可以阅读以下注释:

The TcpClient class provides simple methods for connecting, sending, and receiving stream data over a network in synchronous blocking mode.

对于 Socket 类:

The Socket class allows you to perform both synchronous and asynchronous data transfer using any of the communication protocols listed in the ProtocolType enumeration.

要仅通过 TcpCient 异步发送/接收一些数据,必须调用 GetStream,以通过调用 ReadAsync 和 WriteAsync 方法从中检索底层 NetworkStream/在其上异步读取/写入数据,如下所示TAP 模式(可能使用异步/等待结构)。

要通过套接字异步发送/接收一些数据(我不是专家,但我想我做对了),我们可以通过调用 BeginRead/EndRead BeginWrite/EndWrite(或只是 ReadAsync 或 WriteAsync .. 不公开 TAP 模式 - 即不返回 Task .. 令人困惑)。

首先,知道为什么 .NET 4.5 中的 Socket 类不以任何方式实现 TAP 模式,即 ReadAsync 和 WriteAsync 返回任务(如果以不同方式调用以保持向后兼容的事件)?

无论如何,从 APM 模型方法对构建任务方法很容易,所以假设我调用此异步方法(用于读取)ReadAsyncTAP(返回任务)。

好吗?所以现在假设我想编写一个客户端方法 async Task<Byte[]> ReadNbBytes(int nbBytes)我将从我的代码中调用它以从网络异步读取一定数量的字节。

此方法的实现完全基于 TcpClient 将通过调用 GetStream 获取 NetworkStream,并将包含一个等待 ReadAsync 调用的异步循环,直到缓冲区已满。

基于 Socket 的此方法的实现将包含一个异步循环,等待 ReadAsyncTAP 直到缓冲区已满。

归根结底,从客户端代码的角度来看,我想这没什么区别。在这两种情况下,调用 await ReadNbBytes将立即“返回”。但是,我想这在幕后有所作为......对于依赖 NetworkStream 的 TcpClient,与直接使用 socket 相比,读取是否在任何时候以某种方式阻塞或不阻塞?如果不是,那么在谈论同步阻塞模式时对 TcpClient 所做的评论是错误的吗?

如果有人能澄清,将不胜感激!

谢谢。

最佳答案

TcpClient 流上的异步 I/O 不会阻塞。看起来 MSDN 文档是错误的(您可以通过遵循 NetworkStream 的异步 I/O 调用在 Reflector 中验证这一点)。

Stream 类型很“有趣”:默认情况下,Stream 基类将通过在同步 I/O 上阻塞线程池线程来实现异步 I/O。因此,您永远不想在诸如 MemoryStream 之类的对象上执行异步 I/O,它仅提供同步方法。

NetworkStream 确实提供异步 I/O,因此 NetworkStream 实例上的异步 I/O 实际上是异步的。但情况并非总是如此:FileStream 特别是 usually not asynchronous but it is if you construct the instance just right .

关于为什么 Socket 没有 TAP 方法:这是一个很好的问题!我认为这是一个疏忽,但现在 .NET 4.5 发布了,它看起来像是被故意遗漏了。可能是他们只是不想让 API 过于复杂 - Socket 已经有同步和 两个 异步 API,涵盖了同一组操作(SendSendTo , Receive, ReceiveFrom, Connect, Accept, Disconnect) . TAP 反过来又需要两个额外的异步 API 来提供完整的集合。这至少会导致一个有趣的命名情况(*Async 名称已经被采用,并且他们将为每个操作添加两个以上的 *Async 名称)。

旁注:“附加”API 用于高性能异步 Socket 通信。他们使用 SocketAsyncEventArgs,它不太容易使用,但产生的内存垃圾较少。如果将 TAP API 添加到 Socket,他们会希望同时提供易于使用的版本(包装 Begin/End)和更高性能的版本(包装 Async)。

如果您对为 Socket 制作 TAP 方法感兴趣,可以从 Stephen Toub 的 Awaiting Socket Operations 开始。 (他只为高性能 API 提供包装器)。我对启用了 async 的套接字使用了类似的东西。

关于c# - 处理异步时的 TcpClient 与 Socket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11981106/

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