TCP包装器的GetStream()。Read / Write和Socket的接收/发送之间是否有任何区别

问题描述 投票:0回答:1

如果客户端Socket的定义如下:

args = new SocketAsyncEventArgs();
args.AcceptSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
await args.AcceptSocket.ConnectAsync(host, port);

并且服务器通过这种方式使其连接:

server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(0, port));
server.Listen(0);
var arg = new SocketAsyncEventArgs();
arg.AcceptSocket = await server.AcceptAsync();

byte[]Send/SendAsync中用于服务器和客户端之间传输的Receive/ReceiveAsync是否精确等于NetworkStream,我们通过调用tcpClient.GetStream()进行读写来获得TcpListenerTcpClient

[我不确定这是因为客户端和服务器的SocketType都设置为Stream,并且在这些send/receive协议之间的Streaming中不应有任何数据丢失!

sockets .net-core socketasynceventargs
1个回答
1
投票

差异是API设计之一。

。NET Socket类是Win32's Winsock的OOP API,它本身是从BSD Sockets派生的。

Socket API围绕它自己的发送和接收数据的功能而构建,具有sendrecv之类的功能。在许多平台上,您可以使用操作系统提供的文件系统API来读取和写入套接字,就像读取和写入本地文件一样。

在.NET中,Stream类作为二进制数据的任何源或宿的抽象存在,可以以阻塞或非阻塞(async)的方式读取二进制数据,无论它来自何处(本地磁盘,网络共享上的文件,内存中的缓冲区,TCP连接,UDP连接等)。在此处阅读有关Stream及其抽象的更多信息:https://docs.microsoft.com/en-us/dotnet/standard/io/

关键是,如果您编写一个处理数据的程序或库-则不必为不同类型的IO(文件,内存缓冲区,TCP连接等)一遍又一遍地重复代码。需要使用Stream编写一次代码,然后神奇地将您的代码无需太多工作即可用于许多新地方。

But this comes with a downside of leaky-abstractions。从那以后,我们在过去20到30年的软件工程中获悉,单个接口在每个角色中都不是完美的-例如,MemoryStream始终是非阻塞的,不需要刷新-但[尽管共享相同的API,但C0](NetworkStreamStream API)的行为却大不相同(请记住:接口没有描述行为!),例如它如何在内部缓冲数据(例如Nagle的算法)。 Socket

因此,简而言之:

  • [如果您的程序不需要使用an adapter API提取IO,则只能使用Socket API,而不要使用StreamStream
  • [如果确实需要使用Socket模型传递网络数据,请使用NetworkStreamTcpClient-但要注意Stream的行为,因此应始终使用非阻塞(异步,也称为“ IO重叠”),以避免瓶颈和程序冻结。
  • © www.soinside.com 2019 - 2024. All rights reserved.