Struct über Socket senden?
-
AndyK. schrieb:
Ich hoffe Calculation hat auch einen konstruktor?
Calculation ist doch ein struct und braucht keinen Konstruktor?! Oder versteh ich da was falsch?
-
char buf[4096]; //receive recv(connectedSocket,buf,4096,0); printf(buf); printf("\n"); Calculation *calculation = (Calculation*)&buf; printf("Zahl 1: %d\n", calculation->number1);
-
winfer schrieb:
AndyK. schrieb:
Ich hoffe Calculation hat auch einen konstruktor?
Calculation ist doch ein struct und braucht keinen Konstruktor?! Oder versteh ich da was falsch?
Da Du in deinem Code new und Calculation direkt (und nicht etwa mit struct Calculation) verwendest, schliesse ich daraus, dass Du C++ verwendest.
In C++ sind struct und class bis auf die Default Sichtbarkeit der Member gleich.
Hilfe für den Empfangscode:
//receive Calculation calculation = { }; char* buf = reinterpret_cast<char*>(&calculation); recv(connectedSocket,buf,sizeof(calculation),0); printf("Zahl 1: %d\n", calculation.number1);
Edit:
Ausserdem ist noch anzumerken, dass recv(..) einen Return Wert zurückgibt welcher geprüft sein will. Es könnte ein Fehler aufteten (-1) oder die Verbindung wurde getrennt (0) oder nur die Hälfte der Bytes empfangen worden sein (Return Wert ist dann Anzahl empfangene Bytes). Dann wäre dein Calculation struct nur halb gefüllt.
-
Ich habe das jetzt für den receiver mal so übernommen und zusätzlich noch die den Wert abgefragt den recv() zurück gibt. Als Zahl1 wird nach wie vor 0 ausgegeben, der Wert den recv() zurück gibt ist 24. Wenn ich buf als %s ausgebe ist die Ausgabe leer.
-
Calculation calculation = {42, 21, 1}; send(s, (const char*)&calculation, sizeof(calculation), 0); // mach mal: Calculation calculation = {42, 21, 1}; send(s, (const void*)&calculation, sizeof(calculation), 0);
Was ist der Rückgabewert von "send"?
-
Ok, Kommando zurück. Die Lösung von theta funktioniert so wie es da steht. Hatte beim Ausgeben der Zahl ausversehen %d statt %f stehen
Danke für die Hilfe
-
Ich möchte noch eine Warnung am Rande aussprechen:
Versende lieber keine ganzen Strukturen, sondern Member für Member und setze sie beim Empfänger wieder zusammen.Beim binären Senden & Empfangen muss man sowieso schon auf die Endianess acht geben, wenn du dann auch noch auf das Padding und ähnliches aufpassen musst, dann läufst schnell Gefahr Mist zu produzieren
Also die beiden Tipps:
- Immer Member für Member (fundamentale Typen) empfangen und senden.
- Endianess im Hinterkopf behalten.Grüssli
-
Hi
ich weiss das dieser Thread etwas älter ist aber wollte keinen neuen Thread mit einem ähnlichen Titel starten.
Ich möchte einen Objekt(map,methoden) über einem Socket versenden. Auf was sollte geachtet werden? Außerdem funktioniert es wenn man einfach das Objekt mit const char* castet?
Danke im Voraus!
-
J.Wayne schrieb:
Auf was sollte geachtet werden? Außerdem funktioniert es wenn man einfach das Objekt mit const char* castet?
Versende keine Objekte. Kein struct, class oder sonst etwas. Sende alle Member einzeln und setze sie am anderen Ende wieder zusammen. Wenn du "mehrbytige" Zahlen nicht in Text umwandeln möchtest musst du zusätzlich auf die Endianess achten.
-
kannst du mir vielleicht noch Licht ins dunkle bringen und mir sagen warum ich nicht komplette Objekte versenden soll?
Danke
-
Es hängt halt ganz vom Objekt ab, ob es versendbar ist oder nicht. PODs (Plain Old Data) lassen sich über´s Netzwerk problemlos verschicken, aber komplexe Objekte (solche, die z.B. std::string oder std::vector oder Ähnliches enthalten) erfordern etwas mehr Aufwand.
Der Grund dafür ist ziemlich simpel: Die Daten eines PODs liegen linear im Speicher, das Objekt belegt einen zusammenhängenden Speicherblock. Dieser Block lässt sich ohne Probleme übers Netzwerk verschicken, da alle Daten in diesem Block enthalten sind.
Bei komplexen Objekten ist das eher die Ausnahme, nehmen wir als Beispiel malstd::string
. Dort ist die interne Repräsentation der Daten nicht bekannt, sie könnte z.B. aus drei Zeigern bestehen (Zeiger auf Blockanfang, Zeiger auf Stringende, Zeiger auf Blockende). Wenn du jetzt den String mitstd::string peng; send( socket, &peng, sizeof( std::string ),0 )
verschickst dann sendest du lediglich die drei Zeiger über´s Netzwerk, nicht aber den Stringinhalt. Auf der Gegenstelle werden drei Zeiger empfangen, die in´s Nirvana zeigen und beim Zugriff UB auslösen.
-
> PODs (Plain Old Data) lassen sich über´s Netzwerk problemlos verschicken,
Das glaube ich nicht. Wie Dravere damals schon sagte, kann es da durchaus Probleme mit der Byte-Reihenfolge und dem Alignment bei unterschiedlichen Systemen geben. Besser, man benutzt ein kleines Anwendungsprotokoll (wie JSON).
-
Ok danke dir für die Erklärung.
ich habe so etwas implemtiert und möchte es auf der Gegenseite wieder empfangen.
#include <iostream> #include <map> #include <sstream> class Beispiel{ private: std::map<int,std::string> map1; public: template<typename T> void bla(int bla, T value); template<typename T> T blubb(int blubbVariable); Beispiel(){ } };
Nun habe ich ein Objekt angelegt und habe Versucht so etwas zu machen:
Beispiel *bsp = new Beispiel(); rc=send(s,(const char*)bsp,sizeof(comProtocol),0);
Wie kann man dies übertragen bzw mit recv empfangen?
-
J.Wayne schrieb:
Wie kann man dies übertragen bzw mit recv empfangen?
Nein, so hast du keine Chance. Wie DocShoe schon sagte, std::string/std::map fordern Speicher auf dem Heap an, du würdest nur Pointer verschicken. Du musst die Kompontenten auflösen und einzeln senden.
@DocShoe Dank Padding sollte man das auch bei "flachen" Structs so machen, auch wenn man natürlich Glück haben kann und es funktioniert. Aber man weiß ja nie.
-
J.Wayne schrieb:
...
Ich bin froh, dass du die Antworten der anderen durchgelesen hast...
Im ernst, du hast genau nichts davon getan, was die anderen dir geraten haben!
Schalte dein Hirn ein und lies von vorne.
-
Meinem Vorredner sollte ich nicht antworten aber ich konnte mich nicht zurückhalten. Es ist halt nicht jeder ein Programmierking und deswegen existieren auch solche Foren um Fragen zu stellen. Falls du auf die Fragen nicht eingehen möchtest, behalte deine Meinung für dich.
Danke dir cooky451 und natürlich auch DocShoe, für die ausführliche Beschreibung.
Mal schauen wie ich das jetzt versende :S
-
Jodocus schrieb:
> PODs (Plain Old Data) lassen sich über´s Netzwerk problemlos verschicken,
Das glaube ich nicht. Wie Dravere damals schon sagte, kann es da durchaus Probleme mit der Byte-Reihenfolge und dem Alignment bei unterschiedlichen Systemen geben. Besser, man benutzt ein kleines Anwendungsprotokoll (wie JSON).
Wenn man für mehrere Plattformen entwickelt gebe ich dir recht, aber die meisten Hobby-/Amateurprogrammierer tun das wohl nicht und daher bin ich auf diesen Punkt nicht eingegangen.
-
Ich wollte mich nochmals melden. Ist es möglich das Object als char* umzuwandeln und dies dann über einen Socket zu versenden oder entsteht dabei, dass von euch angesprochene Zeigerproblem mit string-Typen?
Ich brauch definitiv eine Lösung für die Versendung der Daten. Wie würdet ihr das Objekt(Programmcode s. oben) versenden?
Grüße
-
Das kommt ganz darauf an, was du unter "zu char* umzuwandeln" verstehst. Ein einfacher Cast reicht definitiv nicht aus, da hast du die bereits angesprochenen Probleme. Aber du kannst das Objekt in eine zusammenhängende Textdarstellung formatieren, die dann gesendet werden kann (die Gegenseite muß dieses Format dann kennen und parsen, um daraus wieder das Objekt zu rekonstruieren):
std::istringstream data; data<<map1.size()<<'\n'; for(auto it=map1.begin();it!=map1.end();++it) data<<it->first<<'\t'<<it->second<<'\n'; std::string text=data.str(); send(text.c_str());
-
Ich meinte auch mit "zu char* umzuwandeln" einen cast auf char*. Ich habe gehofft, dass ein einfacher Cast möglich ist aber Pusstekuchen.
ich werde versuchen das irgendwie doch noch auf die Beine zubekommen
Danke