In diesem Short möchte ich auf die Identifikation von Netzwerknachrichten in Spielen, aber auch generell eingehen.
Kürzlich hatte ich mal wieder ein bisschen in altem Code gestöbert und bin dabei auf eine Netzwerk-Implementierung gestoßen. Als ich sah, wie ich damals die verschiedenen Nachrichten identifiziert hatte, kam mir glatt das Grauen. Deshalb möchte ich nun eine effizientere Methode vorstellen, damit hoffentlich ein paar Programmierer die in das Thema einsteigen nicht den gleichen Fehler begehen.
Aber wie hatte ich nun die Nachrichten aufgebaut? In Spielen ist es sinnvoll den Typ der Nachricht zu markieren, wie z.b. eine Nachricht die für den Chat gedacht ist. Dafür hatte ich dann folgendes geschrieben:
Send(“ChatMessage|” + msgText);
Ja, da kommt einem die Gänsehaut ^^, doch aus Fehlern lernt man. Was hier falsch gelaufen ist, ist die Länge der Nachricht, gerade in größerem Maßstab gedacht, wenn sekündlich Chat Nachrichten geschrieben werden. Eine Nachricht mit einer String zu identifizieren ist weder effizient, noch zielführend, da eine String eine große Anzahl von bytes in den Stream schreiben müssen. Daher hier nun ein Lösungsansatz.
Wenn man sich überlegt, wie viele Nachrichtentypen man benötigt wird man häufig eine recht kleine Zahl haben, z.b. 64. Da die Netzwerk Nachrichten als byte Stream versendet werden, was ist da nicht naheliegender als ein extra byte (0-255) welcher den Typ angibt?
Das heißt einfach das man die Nachrichtendaten am Anfang um ein byte erweitert, den entprechend auf der Empfägerseite wieder ausließt und den Rest der Nachricht in das gewünschte Format konvertiert.
Einige werden jetzt vielleicht sagen: “Das ist doch total unübersichtlich, einfach eine Zahl!”. Das stimmt durchaus, doch wenn man z.b. in C# arbeitet, kann man sich eines netten kleinen Tricks bedienen.
Man erstellt ein enum z.b. “enum MessageType” und schreibt dort mit Namen und Beschreibung den Typen auf und leitet diesen enum dann von byte ab. Natürlich muss dann auch für jeden Wert im enum ein eindeutiger byte Wert zugeordnet werden.
1
2
3
4
5
| public enum MessageType : byte
{
LoginMessage = 0,
ChatMessage = 1,
} |
public enum MessageType : byte
{
LoginMessage = 0,
ChatMessage = 1,
}
Und schon hat man detailierte ID’s, ohne großen Speicherbedarf zu benötigen. Und falls einem ein byte doch nicht reichen sollte, nimmt man z.b. einfach einen ushort.