Strukturen speichern/senden
-
Ich weiß zwar nicht, was du genau meinst, aber alle serialisierbaren Klassen können z.B. von einer abstrakten Klasse Serializable erben. Dann kannst du übergebene Strukturen serialisieren lassen, ohne deren Details zu kennen.
-
DarkShadow44 schrieb:
Danach wird, wenn die 1.Struct gesendet wird, auch die 2.Struct gesendet.
Zusammen haben sie die Größe "sizeof(struct1)+(sizeof(struct2)" .Nö, das ist nicht der Fall. Was gesendet wird, ist struct1 (inklusive dem Zeiger Rest, was nie Sinn machen kann) und sizeof(struct2) Bytes, die hinter s1Struct1 liegen. Und das ist bestimmt nicht deine zweite struct. Dass dir das nicht um die Ohren fliegt, ist reine Glückssache.
DarkShadow44 schrieb:
Auf dem Heap liegen sie, da ohne das die 2.Struct gar nicht empfangen wurde.
Frag aber nicht warum
Wenn du ungültige Speicherzugriffe im Programm hast, brauchst du dich über eigenartiges Verhalten nicht wundern. Mach new und delete wieder weg. Müsste sowieso delete[] t heißen.
Außerdem: was ist denn sprintf_s für wüstes Zeug? Hab ich ja noch nie gehört und hat mit C++ auch nicht mehr viel zu tun. Und warum char-Arrays statt std::string? Wieso fopen usw. statt file streams?
-
Die Strukturen wurden aber schon korrekt gesendet....
Oder war das nur Zufall und weil Server und Client auf dem selben Rechner liegen ?Wie würdest du denn eine Struktur übergeben lassen, von der der Inhalt unbekannt ist ? Ich habe sie halt asl "char*" und Länge übergeben.
Ich meine:
InitNetwork(????? dataStrukt,int size) { }sprintf_s schreibt Text in einen buffer.
Und warum char-Arrays statt std::string? Wieso fopen usw. statt file streams?
Ich habe eher mit C angefangen, deshalb verwende ich solche Sachen häufiger

-
DarkShadow44 schrieb:
Die Strukturen wurden aber schon korrekt gesendet....
Oder war das nur Zufall und weil Server und Client auf dem selben Rechner liegen ?Dass zwei direkt nacheinander mit new erzeuge Objekte direkt hintereinander liegen, ist nicht ganz abwegig, aber reiner Zufall.
DarkShadow44 schrieb:
Wie würdest du denn eine Struktur übergeben lassen, von der der Inhalt unbekannt ist ? Ich habe sie halt asl "char*" und Länge übergeben.
Ich meine:
InitNetwork(????? dataStrukt,int size) { }Wie schon gesagt, du hast eine abstrakte Klasse Serializable:
class Serializable { public: virtual void serialize(Stream& stream,...)=0; virtual void unserialize(Stream& stream,...)=0; };... von der alle serialisierbaren Klassen erben.
Irgendeine serialisierbare Klasse kannst du dann also mit InitNetwork(const Serializable& dataStrukt) übergeben. Natürlich kannst du auch einen fertigen Stream oder Buffer übergeben, in dem die gewünschte(n) Struktur(en) schon fertig serialisiert sind.
Um serialize & Co. kommst du nicht herum, da mit char-Casterei grundsätzlich keine Strukturen mit Zeigern (ob direkt oder indirekt durch Container-Objekte wie string und vector) serialisiert werden können. Und ohne Zeiger kommst du nicht mal bis vor die Haustür, geschweige denn irgendwo hin.
-
ich möchte aber nur eine einfache struct übergeben:
struct _data { char name[20]; int Typ; char Message[100]; }; _data data; void main() { /*.....*/ InitNetwork(data,sizeof(_data)); /*.....*/ }Ist das so nicht machbar ?
Um serialize & Co. kommst du nicht herum, da mit char-Casterei grundsätzlich keine Strukturen mit Zeigern (ob direkt oder indirekt durch Container-Objekte wie string und vector) serialisiert werden können.
Ich habe die Strukturen so schon erfolgreich in Textdateien geschrieben und geladen (Siehe Threadanfang)
Du meinst also, das sinnvollste und einfachste wäre, den User ein Interface "ISerialize" verwenden zu lassen ?
Und den Stream + seine Länge übergeben ?
-
DarkShadow44 schrieb:
...
Ist das so nicht machbar ?Klar ist das machbar... ich weiß aber auch nicht, was du erreichen willst.
Aller Wahrscheinlichkeit nach willst du ja immer denselben Strukturtyp übergeben. Dann nimmt InitNetwork diesen eben als Argument und size brauchst du dann auch nicht mehr.Ich habe die Strukturen so schon erfolgreich in Textdateien geschrieben und geladen (Siehe Threadanfang)
Wie schon erwähnt, ist das so nicht möglich und war bisher nur Glück. Und du bist ja auch noch gar nicht vor deiner Haustür angelangt

Du kannst ohne Zeiger keine Listen und sonstige Strukturen variabler Größe serialisieren.Du meinst also, das sinnvollste und einfachste wäre, den User ein Interface "ISerialize" verwenden zu lassen ?
Kommt auf den Fall drauf an... generell ja, wenn du irgendwelche Funktionen hast, die beliebige Strukturen serialisieren können sollen. Sowas hat man aber eher selten.
Und den Stream + seine Länge übergeben ?
Ein Stream kennt seine Länge, die musst du also nicht extra übergeben.
-
Aller Wahrscheinlichkeit nach willst du ja immer denselben Strukturtyp übergeben.
Ich will eine lib erstellen. Der User soll eine beliebige struct übergeben können, die dann gesendet und empfangen wird.
Du kannst ohne Zeiger keine Listen und sonstige Strukturen variabler Größe serialisieren.
Aber eigentlich sollte das doch "erlaubt" sein:
_data data1; char*buffer=(char*)&data1; char*buffer2=new char[sizeof(_data)]; //copy buffer to buffer2 _data*data2=(_data*)buffer2;Ich bin mir ganz sicher, dass sich Strukturen so verbiegen lassen.
Hat bisher (auch über Netzwerk (!) ) wunderbar geklappt.Kommt auf den Fall drauf an... generell ja, wenn du irgendwelche Funktionen hast, die beliebige Strukturen serialisieren können sollen. Sowas hat man aber eher selten.
Die soll der User meiner lib ja implementieren

Sorry für die blöde Frage, aber sind Streams char-Pointern nicht sehr ähnlich ?

Wie soll ich denn eine Struct/int/array in einen Stream schreiben ?Irgendwie finde ich nur I/O - streams zum Lesen/Schreiben auf der Festplatte.
-
DarkShadow44 schrieb:
Ich will eine lib erstellen. Der User soll eine beliebige struct übergeben können, die dann gesendet und empfangen wird.
Dann würde ich ein Buffer/Stream übergeben. Ich als Benutzer hätte jedenfalls keine Lust, extra ein paar Strukturen in einer neuen Klasse zu kapseln, wenn ich mehrere davon versenden will.
Aber eigentlich sollte das doch "erlaubt" sein:
_data data1; char*buffer=(char*)&data1; char*buffer2=new char[sizeof(_data)]; //copy buffer to buffer2 _data*data2=(_data*)buffer2;Ich bin mir ganz sicher, dass sich Strukturen so verbiegen lassen.
Hat bisher (auch über Netzwerk (!) ) wunderbar geklappt.Öh, "erlaubt" ist das, aber das hat nichts mit dem angesprochenen Problem zu tun. Kopiert wird hier allerdings nichts. data2 zeigt jetzt auf uninitialisierten (!) Speicher, der zwar groß genug für ein _data-Objekt ist, aber ein solches wurde dort nicht konstruiert. Falls du mit dem Kommentar meintest, dass hier noch kopiert werden müsste: das geht nur für PODs, in der Regel geht das aber nicht. Insbesondere wenn du Zeiger kopierst, fliegen dir die Destruktoren danach kräftig um die Ohren.
Sorry für die blöde Frage, aber sind Streams char-Pointern nicht sehr ähnlich ?

Nein, Streams abstrahieren das ganze. Ein Stream, der seine Daten im Speicher hält, verwendet intern höchstwahrscheinlich ein Array, aber der Punkt ist, dass der Stream die Daten, die du ihm gibst, auch direkt auf die Festplatte in eine Datei schicken kann oder gleich übers Netzwerk verschicken kann. All das, ohne dass deine Funktionen sich darum kümmern müssen, was der Stream genau macht. Außerdem kümmert er sich automatisch darum, dass immer genug Platz für die Daten vorhanden ist.
Wie soll ich denn eine Struct/int/array in einen Stream schreiben ?
Kommt drauf an... mit den Standardstreams so:
deinStream << deineStruct << deinInt; //erfordert, dass du << für deine Klasse überlädst //oder: deineStruct.serialize(deinStream); //erfordert, dass du serialize implementierst //Arrays gehen natürlich genauso, nur dass du eben jedes Element serialisierst und vorher die Länge in den Stream schreibst. //Sinnvollerweise kapselt man das irgendwo in einer Klasse oder Streamfunktion.Mit Boost.Serialize dann & statt <<.
Bei anderen Streanklassen rufst du eben die passenden Funktionen auf. Bei mir z.B. wären das write, writeString etc.
-
Dann würde ich ein Buffer/Stream übergeben. Ich als Benutzer hätte jedenfalls keine Lust, extra ein paar Strukturen in einer neuen Klasse zu kapseln, wenn ich mehrere davon versenden will.
Ich hätte das in-Stream-Umwandeln dem Benutzer halt gerne abgenommen...
Nochmal, MUSS das dem Benutzer überlassen werden ?Was sind "PODs" ?
Und wo überlade ich den Operator z.B. für eine struct ?
Und wie geht das bei einer struct ?Was mache ich dann, wenn ich einen String unbekannter Länge mit einen Stream empfange ?
Wäre halt toll, wenn das Ganze so vereinfacht würde, dass der Benutzer einen char-Pointer auf die struct übergibt und ich die versende(natürlich in MEINER struct ^^.
-
DarkShadow44 schrieb:
Was sind "PODs" ?
http://en.wikipedia.org/wiki/Plain_old_data_structures
DarkShadow44 schrieb:
Und wo überlade ich den Operator z.B. für eine struct ?
Und wie geht das bei einer struct ?DarkShadow44 schrieb:
Was mache ich dann, wenn ich einen String unbekannter Länge mit einen Stream empfange ?
Ein String hat eine bekannte Länge.
Aber womit lernst du eigentlich C++? Solche Grundlagen sollten in jedem brauchbaren Anfängerbuch stehen...
-
Sorry, ich habe string grade wieder mit char-Pointer verwechselt.
Ein String hat nicht immer eine bekannte Länge, ich meine es macht einen Unterschied ob ich einen 120-char oder einen 10-char String sende...
-
Entweder die Länge vorher angeben oder den String durch \0 terminieren.
-
DarkShadow44 schrieb:
Ein String hat nicht immer eine bekannte Länge, ich meine es macht einen Unterschied ob ich einen 120-char oder einen 10-char String sende...
Unter String versteht man in C++ zunächst zwei Dinge:
- Nullterminiertes
char-Array. Die Nullterminierung bestimmt die Länge. - Instanz von
std::string. Die Methodesize()gibt über die Länge Auskunft.
Allerdings ist nicht jedes
char-Array ein C-String.
- Nullterminiertes
-
Danke schonmal

Ich speichere die einzelnen Werte jetzt mit '\0' terminiert als Textdatei.
Damit lade ich sie:ifstream sss; sss.open ("c:/delta.txt",ios::in); string line; if (sss.is_open()) { while (! sss.eof() ) { getline (sss,line); cout << line << endl; } sss.close(); }Dadurch bricht die Schleife beim ersten '\0' ab. Wie finde ich den raus, wie lang die Textdatei ist ?
Die Methode "length()" gibt's ja bei "ifstream" nicht, genauso wenig wie "str()" .Beim senden stellt das kein Problem dar, da die Länge mitgeliefert wird, aber wie finde ich raus die "Position" im Stream raus ?