C#从套接字读取二进制数据

3
我正在开发一个从套接字读写二进制数据的应用程序。首先,我使用TcpClient创建了一个套接字。但是,我在从套接字中读取数据方面遇到了困难。是否有任何代码示例可以演示如何从套接字中读取二进制数据?
具体来说,有两件事我不明白。第一,我如何知道消息何时“接收”?我需要为此创建某种循环吗?第二:由于我接收到的数据是二进制而不仅仅是普通字符串,因此最佳的读取方式是什么?
谢谢

你有关于文档的任何疑问吗?这里还有一个很好的例子:http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx - Kirk Woll
4个回答

5

微软的TCPClient文档实际上非常有用。

如何从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字节)。
虽然这有点作弊,因为他们只接收一批数据并假设它是完整且正确的消息。只要客户端始终发送相同的内容然后断开连接,它就可以正常工作。
更好的处理方式如下... 如何知道是否接收到消息? 你不知道,你只需继续接收数据,直到没有更多数据为止,然后检查你接收到了什么(或边接收边检查)。
为此,你必须设计消息以包含某种告诉长度的方法(在开头指示长度的整数),或者具有某个消息结束标记(例如回车符),或者具有固定长度的消息。
例如,你的消息规范可能像这样:

DATA hello friend
END

通过查找紧随回车符后的END,您将知道已找到消息的结尾。同样,开头的DATA标记可帮助您确定消息从何处开始并拆分出消息数据。
最佳方法是如何读取这些数据?
发送/接收的所有数据都将以二进制形式传输,您需要对数据进行编码和解码。在示例中,他们使用内置的ASCII编码类GetStringGetBytes方法将二进制数据转换为字符串(反之亦然)。
考虑实施已知协议
我建议(在可能的情况下)使用已知协议,而不仅仅是通过TCP发送纯文本。几乎任何事物都有标准,连接到您的应用程序的任何人都会发现遵循已知和定义的标准更容易。
还有许多预构建的常用协议库,可以为您和您的客户节省麻烦。

1
在这种情况下,我会参考MSDN。具体来说,涉及到TcpClients(维护连接 - 这是您已经在做的),TcpListeners(接受连接并开始通信)以及serialization(将数据转换为/从二进制)。

0
第一步是在TcpClient实例上调用GetStream,这将为您提供一个引用,以便您发送和接收二进制数据的NetworkStream。您可以将其包装在BinaryReader和BinaryWriter中,以发送和接收.NET基元(如Int32、字符串等),或直接使用NetworkStream方法来处理字节数组。您会发现NetworkStream.Read、NetworkStream.BeginRead和NetworkStream.DataAvailable成员非常有用;有关更多信息,请参见http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream_members.aspx

0

通过套接字发送的所有数据都是二进制的。由您来将其解释为其他内容,例如字符串。您可以使用以下函数发送或接收数据。您可以使用从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,而不是直接使用sockets。 - Kirk Woll
读取TCP流要复杂得多,因为stream.Read()可能并不总是读取预期的字节数。 - Pradeep Puranik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接