【发布时间】:2020-08-18 16:10:38
【问题描述】:
我最近开始在 C# 中使用 TCP。我现在正处于我希望客户端接收服务器发送的数据的地步。
我知道不能保证客户端一次接收所有数据。如果发送的数据大小大于客户端缓冲区的大小,则数据将被分批发送。所以我的问题是:如何将我收到的所有数据存储在一个字节数组中,然后在收到所有数据后将其转换为实际消息?
我已将缓冲区大小设置为 1,因此我可以看到当所有发送的数据都不适合缓冲区时会发生什么。这是我在 Client.cs 中调用 stream.BeginRead() 的方法:
// Deliberately setting the buffer size to 1, to simulate what happens when the message doesn't fit in the buffer.
int bufferSize = 1;
byte[] receiveBuffer;
private void ConnectCallback(IAsyncResult result)
{
client.EndConnect(result);
Console.WriteLine("Connected to server.");
stream = client.GetStream();
// At this point, the client is connected, and we're expecting a message: "Welcome!"
receiveBuffer = new byte[bufferSize];
stream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, new AsyncCallback(ReadCallback), stream);
}
private void ReadCallback(IAsyncResult result)
{
int bytesLength = stream.EndRead(result);
// Should be "Welcome!". But of course it's "W", because the bufferSize is 1.
string message = Encoding.UTF8.GetString(receiveBuffer, 0, bytesLength);
Console.WriteLine("Received message: {0}", receivedMessage);
// Reset the buffer and begin reading a new message, which will be "e".
// However, I want the whole message ("Welcome!") in one byte array.
receiveBuffer = new byte[bufferSize];
stream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReadCallback, null);
}
这是发送消息“Welcome!”时的输出:
Connected to server.
Received message: W
Received message: e
Received message: l
Received message: c
Received message: o
Received message: m
Received message: e
Received message: !
我是否应该临时存储数据直到整个消息到达,然后将其转换为字符串?
后续问题:如果 2 条消息彼此紧挨着发送,例如 Welcome!,然后是 What's your name,该怎么办?那我该如何区分这两条消息呢?
【问题讨论】:
-
“我应该临时存储...”。是的。您也可以在字符串/数据包前面加上它的长度(如果您愿意的话)。 “如果有 2 条消息……”。你不能。为此,您需要一个 protocol。您可以使用分隔符(例如 - 例如 - 每个 message 之后的强制换行符)。如果您使用数据包大小作为前缀,那么您也可以使用它来区分数据包。通常不需要重新发明轮子,有许多现成的协议和库可以做到这一点。提示:您正在发送/接收 消息...
-
只是为了澄清-即使客户端的缓冲区比数据大,仍然不能保证一次接收到所有数据。这实际上取决于网络如何缓冲数据 - 不一定是代码中定义的缓冲区。 MSDN 声明 NetworkStream.Read -“此方法读取缓冲区参数中可用的尽可能多的数据,并返回成功读取的字节数。”您总是想检查实际读取的字节数。
-
如果有帮助,您正在研究的主题称为“TCP 消息帧”。这个页面有一些基本的想法:blog.stephencleary.com/2009/04/message-framing.html
标签: c# .net networking tcp tcpclient