NetworkStream.Write vs. Socket.Send

本文关键字:Send Socket vs Write NetworkStream | 更新日期: 2023-09-27 18:00:50

我有一个使用自定义FTP库的c#应用程序。现在我使用Socket.Send来发送数据,但我想知道用Socket启动NetworkStream并使用NetworkStream.Write是否更好。

使用其中一个比使用另一个有什么好处吗?

NetworkStream.Write vs. Socket.Send

NetworkStream的优势主要来源于它是StreamSocket的缺点是从抽象I/O源(如Stream(读取和写入的通用代码无法处理Socket

NetworkStream的主要用例是,您在其他地方有一些从Stream读取或写入的代码,并且您希望可以将其与Socket一起使用。你会知道如果在这种情况下,那么NetworkStream将是一个很大的帮助!

例如,您有一个通信库,并且支持从文件、命名管道和TCP/IP序列化消息。I/O类的理想选择是Stream。然后,序列化方法可以接受FileStreamPipeStreamNetworkStream。它甚至会接受MemoryStream。这是抽象的好处,因为在我们创建流之后,方法可以与它交互,而不知道它是什么类型的流。

从这个意义上讲,NetworkStream使用适配器设计模式。它将Socket API调整为Stream API,以便期望Stream的客户端可以使用它

最后,问题是,如果NetworkStreamSocketStream适配器,我们应该使用哪一个?好吧,如果您需要Stream,那么NetworkStream是您唯一的选择。如果您不需要Stream,那么您可以使用您最熟悉的API。如果您已经成功使用Socket,则没有迫切的理由切换到NetworkStream

您可以将NetworkStream的创建与抽象Stream的创建分开,这样您就可以更改传输或简单地创建用于测试的Stream存根。

由于方法本身的问题——内部的NetworkStream.Write有唯一的操作(除了状态检查(streamSocket.Send(buffer, offset, size, SocketFlags.None);——所以它与在套接字上调用它基本相同。

使用NetworkStream::Write.NET Framework实现的一个缺点是,如果底层网络(OSI层1-4(无法接收整个数据缓冲区,则您不会意识到(可能除了检查.NET Networking性能计数器。(

不可靠

类似的内容出现在Microsoft.NET Framework的NetworkStream::WriteSystem.dll:

try
{
    socket.Send(buffer, offset, size, SocketFlags.None);
}
/* ... catch{throw;} */

请注意,返回值(表示Send()写入的字节数(是如何被丢弃的。这表明NetworkStream::Write对于低于标准的网络(漫游/无线(或可能成为IO绑定(超过可用带宽(的网络来说是不可靠的

不止一个实现

您可以找到其他实现,这些实现会写入所有字节,直到所有buffer都被写入(或发生其他故障(。这是一种标准的发送数据的方法,并且总是表现出以下行为:

var count = 0;
while (count < size)
{
    count += socket.Send(buffer, offset + count, size - count, ...);
}

这是什么意思

您可以直接调用Socket::Send来编写正确可靠的send((代码,而不能通过调用NetworkStream::Write来编写正确可信的send(代码。

顺便说一句,NetworkStream的其他变体没有BCL拆卸所显示的相同问题(见mono,cosi2(,尽管他们尽了最大努力,但仍有其他变体显示出类似的问题(见floronefx(。

参考文献

  1. Github上的Mono存储库
  2. FlourineFxSL源代码
  3. BitBucket上的cosi2存储库(通过searchcode.com(