【问题标题】:How does TcpClient improve on raw Sockets?TcpClient 如何改进原始套接字?
【发布时间】:2020-04-27 11:15:36
【问题描述】:

我在几个地方看到人们说TcpClientNetworkStream 比原始Socket 更受欢迎,例如,它们有助于“数据框架”,从而可以从服务器接收到的消息需要解析并拼凑到原始消息中的任意数量的片段(不保证 1:1 调用发送/接收)

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

NetworkStream 读取数据似乎与从Socket 接收数据非常相似,所以有人能解释一下它如何让我作为 TCP 编码新手的生活更轻松吗?

【问题讨论】:

  • It surely cannot magically piece messages back together since that information isn't transmitted over TCP你确定吗?
  • 是的。 TCP 是字节流,而不是像 UDP 这样的数据报。在单个 send() 调用中发送 N 个字节不会导致在另一端的单个 recv() 调用中返回相同的确切缓冲区。它可能,但不能保证。设备可能会将其分成更小的块或将其与前一个或下一个块混在一起。它可能会受到 MTA 设置的影响,因为它通过各种网络进行路由。边界标记不是 TCP 协议的一部分,因此应用程序必须根据内容确定这些边界的位置。 TcpClient 没有应用协议的概念。
  • 那么,它有什么帮助呢?我可以看到 NetworkStream.DataAvailable 属性,但还有什么?
  • 我最好的猜测是 1)它将套接字(及其状态)的概念与其数据流分开,2)它提供了一个以客户端为中心的 API(Socket 既不知道也不关心它是哪一端),以及 3)它的 Async API 与 async/await 兼容,而 Socket 仍然使用 IAsyncResultBegin/End 方法。

标签: c# .net tcp tcpclient


【解决方案1】:

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

TcpClient 抽象出了许多不同的建立 Socket 的方法,只提供了一些非常常用的方法。此外,它使处理缓冲区之类的事情变得更容易。同样NetworkStream 抽象出许多不同的从套接字读取/写入的方法,并允许您在NetworkStream 之上使用更多熟悉的流。比如TextWriterTextReader

它们在数据框架方面并没有真正的区别。您仍然需要知道要查找的数据在哪里开始和结束。虽然如果您的数据框架是一个很好的旧文本行,那么 NetworkStream 之上的 TextReader 和 TextWriter 会非常幸福。

IMO,TcpClient 和 NetworkStream 最大的单一优势是异步方法和开发非阻塞 IO 客户端/服务器代码的极其简单的方法。虽然您可以使用直接 Socket 来做到这一点,但这要困难得多,也更复杂。

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

当然,您可以通过直接与 Socket 交互来完成 TcpClientNetworkStream 为自己提供的所有操作,但是您会发现自己编写了很多重复的代码,其中包含很多已经考虑过的边缘情况TcpClientNetworkStream

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-22
    • 1970-01-01
    • 1970-01-01
    • 2020-02-29
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多