嗨,我有问题使用自定义二进制协议分组数据包。 目前服务器端代码如下所示。使用二进制协议的TCP帧
public void HandleConnection(object state)
{
TcpClient client = threadListener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
byte[] data = new byte[4096];
while (true)
{
int recvCount = stream.Read(data, 0, data.Length);
if (recvCount == 0) break;
LogManager.Debug(Utility.ToHexDump(data, 0, recvCount));
//processPacket(new MemoryStream(data, 0, recvCount));
}
LogManager.Debug("Client disconnected");
client.Close();
Dispose();
}
我一直在看包的十六进制转储,有时整个包是一个炮打响,让我们说所有的20个字节。其他时候它是分散的,我如何缓冲这些数据才能够正确地将它传递给我的processPacket()方法。我试图只使用一个字节的操作码头,我是否应该在头中添加一个像(ushort)contentLength一样的东西?我试图使协议尽可能轻量级,而且这个系统不会发送非常大的数据包(< 128字节)。
我正在测试的客户端代码如下所示。
public void auth(string user, string password)
{
using (TcpClient client = new TcpClient())
{
client.Connect(IPAddress.Parse("127.0.0.1"), 9032);
NetworkStream networkStream = client.GetStream();
using (BinaryWriter writer = new BinaryWriter(networkStream))
{
writer.Write((byte)0); //opcode
writer.Write(user.ToUpper());
writer.Write(password.ToUpper());
writer.Write(SanitizationMgr.Verify()); //App hash
writer.Write(Program.Seed);
}
}
}
我不知道这可能是什么搞乱了起来,和二进制协议似乎并没有在网络上很多信息,尤其是在C#参与。任何评论会有帮助。 =)
解决与此,不知道它是否正确,但它似乎给我的处理程序,他们需要什么。
public void HandleConnection(object state)
{
TcpClient client = threadListener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
byte[] data = new byte[1024];
uint contentLength = 0;
var packet = new MemoryStream();
while (true)
{
int recvCount = stream.Read(data, 0, data.Length);
if (recvCount == 0) break;
if (contentLength == 0 && recvCount < headerSize)
{
LogManager.Error("Got incomplete header!");
Dispose();
}
if(contentLength == 0) //Get the payload length
contentLength = BitConverter.ToUInt16(data, 1);
packet.Write(data, (int) packet.Position, recvCount); //Buffer the data we got into our MemStream
if (packet.Length < contentLength + headerSize) //if it's not enough, continue trying to read
continue;
//We have a full packet, pass it on
//LogManager.Debug(Utility.ToHexDump(packet));
processPacket(packet);
//reset for next packet
contentLength = 0;
packet = new MemoryStream();
}
LogManager.Debug("Client disconnected");
client.Close();
Dispose();
}
嗯,我会将contentLength添加到标题,谢谢。我在processPacket()中使用了一个二进制读取器,但显然这只是在传递一个部分数据包时才会失败。 – Endian 2009-08-12 20:02:14
@Endian:你为什么不通过网络流而不是数据包呢? – 2009-08-12 20:03:29
@Jon:数据包更多的是我的二进制读取器可以读取而不会产生缓冲区溢出的块。我已经按照我现在所做的来编辑原文,在你的建议之后,它似乎在工作,感谢您的帮助。 :) – Endian 2009-08-12 20:39:11