Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 处理异步时TcpClient与Socket_C#_Sockets_Asynchronous_Tcpclient_Async Await - Fatal编程技术网

C# 处理异步时TcpClient与Socket

C# 处理异步时TcpClient与Socket,c#,sockets,asynchronous,tcpclient,async-await,C#,Sockets,Asynchronous,Tcpclient,Async Await,这不是另一个TcpClient vs套接字 TcpClient是围绕Socket类的包装器,用于简化开发,还公开了底层Socket 还是 在TcpClient类的MSDN库页面上,可以阅读以下备注: TcpClient类提供了连接、发送、, 以及以同步阻塞模式通过网络接收流数据 对于套接字类: Socket类允许您同时执行同步和 使用任何通信协议的异步数据传输 在ProtocolType枚举中列出 要仅通过TcpCient异步发送/接收某些数据,必须调用GetStream,以检索底层Networ

这不是另一个TcpClient vs套接字

TcpClient是围绕Socket类的包装器,用于简化开发,还公开了底层Socket

还是

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

TcpClient类提供了连接、发送、, 以及以同步阻塞模式通过网络接收流数据

对于套接字类:

Socket类允许您同时执行同步和 使用任何通信协议的异步数据传输 在ProtocolType枚举中列出

要仅通过TcpCient异步发送/接收某些数据,必须调用GetStream,以检索底层NetworkStream,通过调用其上的ReadAsync和WriteAsync方法,按照TAP模式(可能使用异步/等待构造),从底层NetworkStream异步读取/写入数据

要通过套接字异步发送/接收一些数据(我不是专家,但我认为我做对了),我们可以通过调用BeginRead/EndRead BeginWrite/EndWrite(或者只是ReadAsync或WriteAsync..不公开TAP模式-即不返回任务..来直接从套接字实例本身读/写数据

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

无论如何,从APM模型方法对构建任务方法非常简单,所以假设我将此异步方法(用于读取)称为ReadAsyncTAP(返回任务)

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

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

基于套接字的此方法的实现将包含一个异步循环,等待ReadAsyncTAP,直到缓冲区满为止

最后,从客户机代码的角度来看,我认为这没有什么区别。在这两种情况下,对
wait ReadNbBytes
的调用将立即“返回”。然而,我想这在幕后会有所不同。。。 对于依赖NetworkStream的TcpClient,与直接使用socket相比,读取是否会在任何时候以某种方式阻塞?如果没有,在谈到同步阻塞模式时,是否对TcpClient的评论是错误的

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


谢谢。

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

Stream
类型是“有趣的”:默认情况下,
Stream
基类将通过在同步I/O上阻塞线程池线程来实现异步I/O。因此,您永远不希望在像
MemoryStream
这样的东西上执行异步I/O,因为它只提供同步方法

NetworkStream
确实提供了异步I/O,因此
NetworkStream
实例上的异步I/O实际上是异步的。但情况并非总是如此:
FileStream
尤其如此

关于为什么
Socket
没有TAP方法:这是一个非常好的问题!我认为这是一个疏忽,但现在.NET4.5发布了,看起来它是故意被遗漏的。这可能是因为他们不想使API过于复杂-套接字已经有了同步和两个异步API,涵盖了相同的操作集(
Send
SendTo
ReceiveFrom
Connect
Accept
Disconnect
)。TAP反过来需要两个额外的异步API来完成整个集合。这至少会引起一个有趣的命名情况(已经使用了
*Async
名称,并且他们会为每个操作再添加两个
*Async
名称)

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


如果您对为
Socket
制作TAP方法感兴趣,那么Stephen Toub的方法是一个很好的起点(他只为高性能API提供包装器)。我在我的
异步
支持的套接字中使用了类似的东西。

我喜欢Stepgen Toub的解决方案,但我认为你会是编写类似内容的人。:)与命名类似的情况是
WebClient
,其中
*Async
名称用于EAP(基于事件的异步模式)方法。他们解决这个问题的方法是将TAP方法命名为
*taskancy
@d4wn:Working on it.:)由于我的日常工作疯狂,这项工作可能要到2013年才能完成(@svick:Socket
Socket
中的命名情况更为棘手。由于整个BCL中有一个类,他们决定使用
*Async
来表示“使用
SocketAsyncEventArgs
”因此,您可以对APM样式的包装使用
*taskancy
,而不是EAP。如果您同时遵循现有的TAP和
Socket
约定,那么
SocketAsyncEventArgs
样式的包装将使用
*asyncync
。对于已经过度使用的包装来说,这些方法既丑陋又令人困惑