Buffer unbekannter Größe mit void anhängen
-
Hi!
Ich habe da ein Netzwerk Problem.Ich schreibe gerade einen Chatclient für's Battle.net. Um die Daten die ich verschicke und empfange übersichtlicher zu haben, habe ich mir Klassen gemacht.
Das sieht einmal so aus:class CBNCS { public: BYTE MessageStart; //Immer 0xFF! BYTE MessageID; //Die ID halt WORD MessageLength; //Die gesamte Datenlänge inkl. header void *Data; //Die Daten die dann kommen };Das ist der Header des Protokolls mit dem das Battle.net kommuniziert. Dieser muss immer in diesem Format versendet werden.
Data ist dann die eigentliche Nachricht, die ich verschicke. Meistens ist das noch eine weitere komplette klasse die ich da drann hänge. An sich funktioniert das auch, allerdings steht vor den eigentlichen Daten, die in der Klasse enthalten sind, die Adresse der Klasse im Buffer. Da die Daten vom Server dann nichtmehr richtig interpretiert werden können, werde ich natürlich gekickt.Ich weise das Ganze so zu:
BNCS.Data = &AuthInfo; //AuthInfo ist eine Variable einer Klasse!Verschickt wird das Ganze so:
rc = send(s,(char *)&BNCS,(sizeof AuthInfo)+4,0); //+4 wegen headerWie kriege ich diese Adresse vom Anfang des Buffers weg?
Das Problem ist wie gesagt, dass ich nicht weiß wie groß Data ist. Natürlich könnte ich 1000 mal Copy und Paste machen, dann geht es auch, aber da gibt es doch bestimmt eine konfortablere art!?
-
Du kannst natürlich nicht direkt Objekt-Instanzen verschicken, dondern eben Daten, die du dann auf Client-Seite evtl. wieder entsprechend zurückcasten kannst. Du musst also dafür sorgen, dass die Daten im Speicher direkt hintereinander stehen. Mit Pointern geht das so nicht - du kannst aber auch die Daten in zwei Schritten (also zweimal send) verschicken...
-
Du solltest beachten, dass man keine Strukturen oder Klassen über das Netz senden kann; sondern immer nur bytes (eines nach dem anderen).
Auch wird meistens eine etwas andere Byte-Order verwendet als bei Intel-Prozessoren üblich (Network-Byte-Order entspricht meistens dem Motorola-Format: Also das höchtse (MSB) Byte zu erst und als letzten das niedrigste Byte (LSB)).
Siehe auch: Windows Sockets: Byte Ordering: http://msdn.microsoft.com/library/en-us/vccore/html/_core_windows_sockets.3a_.byte_ordering.aspDein Problem lässt sich eigentlich mit einer Basisklasse und mehreren abgeleiteten Klassen lösen:
Die Basisklasse enthält den Header (der ja immer benötigt wird):class Base { virtual void Send(...); };In einer abgeleiteten Klasse überschreibst Du jetzt die Send um noch mehr Daten anzufügen:
class MoreData : public Base { virtual void Send(...) { Base::Send(); // schicke zuerst mal den Header // Sende jetzt noch weitere Daten } };usw....
-
Oder du legst dir einen Zwischenpuffer mit der Größe x+4 an, in den du hintereinander weg erst die Header-Elemente und dann die Daten packst - den kannst du dann am Stück verschicken.
-
Nur um nicht den Eindruck zu erwecken das mehrere send(...) aufrufen auch automatisch in mehrere TCP-Pakete münden... das ist natürlich nicht der Fall, da der TCP-Layer das ganze optimiert und auch zusammenfasst...