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
方法。