【问题标题】:C# read binary data from socketC#从套接字读取二进制数据
【发布时间】:2010-09-13 23:43:14
【问题描述】:

我正在开发一个从套接字读取和写入二进制数据的应用程序。所以首先我用 TcpClient 创建一个套接字。但我坚持从套接字读取数据。有没有关于如何从套接字读取二进制数据的代码示例?

具体,有两件事我不明白。首先,我如何知道消息是否“收到”?我需要为此创建某种循环吗?第二:读取这些数据的最佳方法是什么,因为我收到的数据是二进制的,而不仅仅是普通的字符串。

谢谢

【问题讨论】:

标签: c# sockets tcp binary


【解决方案1】:

来自微软的TCPClient documentation 实际上非常有用。

如何从 TCPClient 读取数据

Microsoft 示例中从套接字读取数据的关键部分是这样的:

// Get the stream
NetworkStream stream = client.GetStream();
Byte[] data = new Byte[256];

// String to store the response ASCII representation.
String responseData = String.Empty;

// Read the first batch of the TcpServer response bytes.
int bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);

它们使用TCPClient 类的GetStream 方法并从流中读取所有可用数据(最多256 个字节)。

不过,这有点作弊,因为他们只是接收到大量数据并假设它是完整且正确的消息。只要您的客户端是 100% 可预测的,它就会正常工作,因为它总是发送相同的内容然后断开连接。

以下更好的处理方式...

您如何知道是否收到了消息?

你没有,你只是继续接收数据,直到没有更多的数据,然后检查你收到了什么(或检查你去)。

为此,您必须设计消息以包含某种方式来告知长度(开头的整数表示长度),或者有一些消息结束标记(例如回车)或有一个固定长度的消息。

例如,您的消息规范可能是这样的:

数据 你好朋友
结束

通过查找 END 后跟回车,您将知道您已找到消息的结尾。同样,开头的 DATA 标记可帮助您判断消息从何处开始并拆分消息数据。

读取这些数据的最佳方法是什么?

所有发送/接收的数据都是二进制的,您需要对数据进行编码和解码。在示例中,他们使用内置的 ASCII 编码类 GetStringGetBytes 方法将二进制数据转换为字符串(反之亦然)。

考虑实现一个已知协议

我建议(在可能的情况下)使用已建立的协议,而不仅仅是通过 TCP 发送纯文本。几乎所有东西都有标准,任何连接到您的应用程序的人都会发现遵循已知和定义的标准更容易。

还有许多用于常用协议的预构建库,为您和您的客户省去麻烦。

【讨论】:

    【解决方案2】:

    在这种情况下,我将遵从 MSDN。具体来说,使用TcpClients(维护连接 - 您已经在做)、TcpListeners(接受连接并开始通信)以及serialization(将数据转换为二进制数据)。

    【讨论】:

      【解决方案3】:

      通过套接字发送的所有数据都是二进制的。您可以将其解释为其他内容,例如字符串。您可以使用这些函数来发送或接收数据。您可以使用从NetworkStream stream = client.GetStream(); 获得的 NetworkStream 调用它们。请注意,这些函数首先发送一个带有数据大小的 int。

      public void send(NetworkStream stream, byte[] buf) {
          stream.Write(BitConverter.GetBytes(buf.Length), 0, 4);
          stream.Write(buf, 0, buf.Length);
      }
      
      public byte[] receive(NetworkStream stream) {
          byte[] lengthBytes = new byte[4];
          int read = stream.Read(lengthBytes, 0, 4);
          // read contains the number of read bytes, so we can check it if we want
          int length = BitConverter.GetInt32(lengthBytes);
          byte[] buf = new byte[length];
          stream.Read(buf, 0, buf.length);
          return buf;
      }
      

      【讨论】:

      • OP 使用的是 TcpClient,而不是直接使用套接字。
      • 读取 tcp 流要复杂得多,因为 stream.Read() 可能并不总是读取预期的字节数。
      【解决方案4】:

      第一步是在 TcpClient 实例上调用 GetStream,它为您提供对用于发送和接收二进制数据的 NetworkStream 的引用。您可以将其包装在 BinaryReader 和 BinaryWriter 中以发送和接收 .NET 基元(如 Int32s、Strings 等)或直接将 NetworkStream 方法用于字节数组。您会发现 NetworkStream.Read、NetworkStream.BeginRead 和 NetworkStream.DataAvailable 成员很有用;请参阅http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream_members.aspx 了解更多信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-24
        • 2020-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-16
        • 2014-06-07
        相关资源
        最近更新 更多