Hey, ich habe ein Problem, Pakete mit einem benutzerdefinierten Binärprotokoll zu trennen. Derzeit sieht der Server-Code so aus.TCP-Framing mit binärem Protokoll
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();
}
Ich habe den Hex-Dumps der Pakete zu beobachten, und manchmal das ganze Paket kommt in einem Schuss, lassen Sie sich alle 20 Bytes sagen. Andere Zeiten, in denen es fragmentiert ist, wie muss ich diese Daten puffern, um sie korrekt an meine processPacket() -Methode übergeben zu können. Ich versuche, nur einen einzelnen Byte-Opcode-Header zu verwenden, sollte ich etwas wie eine (ushort) contentLength auch zum Header hinzufügen? Ich versuche, das Protokoll so leicht wie möglich zu machen, und dieses System wird nicht sehr große Pakete senden (< 128 Bytes).
Der clientseitige Code, den ich testen möchte, ist wie folgt.
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);
}
}
}
Ich bin mir nicht sicher, ob das sein könnte, was es vermasselt, und Binärprotokolls scheint nicht viele Informationen im Internet, insbesondere bei der C# beteiligt ist. Jeder Kommentar wäre hilfreich. =)
Gelöst mit diesem, nicht sicher, ob es korrekt ist, aber es scheint meinen Handlern genau das zu geben, was sie brauchen.
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();
}
Hmm, Ich werde der Kopfzeile eine contentLength hinzufügen, danke. Ich benutze einen binären Leser in processPacket(), aber offensichtlich scheitert es schrecklich, wenn es nur ein Teilpaket übergeben wird. – Endian
@Endian: Warum reicht es nicht einfach den Netzwerk-Stream statt ein Paket? –
@ Jon: Packet mehr im Sinne eines Stücks, das mein binaryReader lesen kann, ohne einen Buffer Underrun zu bekommen. Ich habe den ursprünglichen Beitrag mit dem, was ich gerade mache, nach deinem Vorschlag bearbeitet und es scheint zu funktionieren, danke für die Hilfe. :) – Endian