嗨,我有問題使用自定義二進制協議分組數據包。 目前服務器端代碼如下所示。使用二進制協議的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