【发布时间】:2017-07-08 21:40:42
【问题描述】:
我正在开发一款多人游戏,但我在解析来自连接的数据包时遇到了问题。当我调试游戏时,它以较低的性能运行并且接收到数据包,当我没有时,数据包没有完全接收到并且 ParsePacket 方法没有被调用。
我的数据包结构是这样的:
2 字节短命令,2 字节短有效载荷大小,(可选)有效载荷字节
IInputStream inputStream = null;
DataReader dataReader = null;
byte[] data = new byte[1024];
IBuffer buffer = data.AsBuffer();
try
{
inputStream = StreamSocket.InputStream;
dataReader = DataReader.FromBuffer(buffer);
dataReader.InputStreamOptions = InputStreamOptions.Partial;
dataReader.ByteOrder = ByteOrder.LittleEndian;
while (connected)
{
await inputStream.ReadAsync(buffer, 1024, InputStreamOptions.Partial);
Debug.WriteLine("Buffer " + buffer.Length);
if (buffer.Length >= PacketHeaderSize)
{
short command = dataReader.ReadInt16();
short payloadSize = dataReader.ReadInt16();
byte[] payload = null;
if (payloadSize == 0)
{
UpdateBuffer(buffer, (uint)(PacketHeaderSize + payloadSize));
Packet packet = new Packet(command, payloadSize, payload);
ParsePacket(packet);
}
else if (payloadSize > 0)
{
if (buffer.Length >= (PacketHeaderSize + payloadSize))
{
payload = new byte[payloadSize];
dataReader.ReadBytes(payload);
UpdateBuffer(buffer, (uint)(PacketHeaderSize + payloadSize));
Packet packet = new Packet(command, payloadSize, payload);
ParsePacket(packet);
}
}
}
}
}
catch (Exception e) {
// ...
}
private void UpdateBuffer(IBuffer buffer, uint bytesRead)
{
if (buffer.Length > bytesRead)
{
byte[] bufferBytes = new byte[buffer.Length - bytesRead];
System.Buffer.BlockCopy(buffer.ToArray(), (int)bytesRead, bufferBytes, 0, (int)(buffer.Length - bytesRead));
buffer = bufferBytes.AsBuffer();
}
else
{
byte[] bufferBytes = new byte[1024];
buffer = bufferBytes.AsBuffer();
}
}
我做错了什么?
【问题讨论】:
-
在编写 uwp 应用程序时,请确保您在问题上有 uwp 标签,uwp 应用程序框架中可用的类与桌面应用程序不同。
-
@ScottChamberlain 我的错,谢谢。
-
如果没有可靠地重现问题的良好 minimal reproducible example 就不可能确定,但您的代码似乎有几乎任何以前不费心研究网络协议的人都会犯的标准错误深入研究网络代码:您期望同时接收所有数据。 TCP 不是这样工作的。套接字是一个字节流,数据一次可以少至一个字节(尽管实际上它通常不是那么糟糕:))。
-
在任何给定的字节消耗状态下,您都需要继续阅读,直到获得所需的所有字节。鉴于您发布的代码,
ParsePacket()根本不被称为 有点奇怪,但预期它可能会被不完整的数据调用当然是合理的,因为您没有做任何事情来确保您'已经读取数据,直到你得到预期的那样多。还有一个问题是,您可以将下一条消息的标头作为当前消息的一部分读取,从而破坏数据流。 -
@PeterDuniho 我知道混合数据包或不完整的数据,我主要担心的是我的代码过于复杂,但我已经更新了我的问题的代码。不过,我对如何将当前的字节流附加到缓冲区非常迷茫。谢谢。
标签: c# uwp network-protocols