C# TcpClient如何改进原始套接字?

C# TcpClient如何改进原始套接字?,c#,.net,tcp,tcpclient,C#,.net,Tcp,Tcpclient,我曾在几个地方看到人们说TcpClient和NetworkStream比原始Socket使用更受欢迎,例如,它们在“数据帧”方面有帮助,从服务器接收的消息可以是任意数量的片段,需要解析并拼接到原始消息中(发送/接收呼叫不保证1:1) 我不明白的是,它在这方面如何更好?它肯定不能神奇地将消息拼凑在一起,因为这些信息不是通过TCP传输的。它不能期望发送关于消息长度的额外数据,否则它将无法与大多数TCP服务器兼容,只有那些使用TcpListener的服务器 从网络流中读取数据似乎与从套接字中接收数据非

我曾在几个地方看到人们说
TcpClient
NetworkStream
比原始
Socket
使用更受欢迎,例如,它们在“数据帧”方面有帮助,从服务器接收的消息可以是任意数量的片段,需要解析并拼接到原始消息中(发送/接收呼叫不保证1:1)

我不明白的是,它在这方面如何更好?它肯定不能神奇地将消息拼凑在一起,因为这些信息不是通过TCP传输的。它不能期望发送关于消息长度的额外数据,否则它将无法与大多数TCP服务器兼容,只有那些使用TcpListener的服务器


网络流中读取数据
似乎与从
套接字中接收数据非常相似,所以有人能解释一下,作为一名TCP新手,它是如何让我的生活更轻松的吗?

这可能有点像问为什么要使用
System.Net.Sockets
(它为
WinSock
提供了一个API,而不是编写我们自己的
WinSock
API

TcpClient
抽象了建立套接字的许多不同方法,并且只提供了一些非常常见的方法。此外,它使处理缓冲区之类的事情更容易。同样地
NetworkStream
抽象了从套接字读写的许多不同方法,并允许您在顶部使用更多的家庭流属于
NetworkStream
。例如
TextWriter
TextReader

在数据帧方面,它们实际上没有任何区别。你仍然需要知道你要查找的数据从何处开始和结束。虽然如果你的数据帧是一行很好的旧文本,那么NetworkStream上的TextReader和TextWriter会让你感到非常高兴

在我看来,TcpClient和NetworkStream最大的单一优势是异步方法和开发非阻塞IO客户机/服务器代码的极其简单的方法。虽然您可以使用直接套接字来实现这一点,但这要困难得多,复杂得多

如果您刚开始,我建议您完全跳过NetworkStream(用于阅读)并使用
System.IO.Pipelines
——它位于
NetworkStream
之上,这将进一步抽象NetworkStream,并加快开发速度


当然,您可以通过直接与套接字交互来完成
TcpClient
NetworkStream
为自己提供的所有功能,但是您会发现自己编写了大量重复的代码,其中包含了许多在
TcpClient
NetworkStream
中已经考虑过的边缘情况灵活地将消息拼凑在一起,因为该信息不是通过TCP传输的。你确定吗?是的。TCP是一个字节流,而不是像UDP那样的数据报。在单个
send()
调用中发送N个字节不会导致在单个
recv()中返回相同的确切缓冲区
在另一端调用。可能会,但不能保证。设备可能会将其拆分成更小的块,或将其与上一个或下一个块组合在一起。在通过各种网络路由时,它可能会受到MTA设置的影响。边界标记不是TCP协议的一部分,因此应用程序必须确定这些边界的位置我们基于内容。
TcpClient
没有应用程序协议的概念。那么,它有什么帮助呢?我可以看到
NetworkStream.DataAvailable
属性,但还有什么?我最好的猜测是1)它将套接字的概念(及其状态)与其数据流分离,2)它提供了一个以客户机为中心的API(
Socket
既不知道也不关心它是哪一端),3)它的异步API与
Async
/
wait
兼容,而
Socket
仍然使用
IAsyncResult
Begin
/
end
方法。