Struct per Netzwerk übertragen
-
struct meinestruktur m1; unsigned char * zeigeraufchar; struct meinestruktur * zeigeraufstruct; zeigeraufchar=(unsigned char*)&m1; zeigeraufstruct=(struct meinestruktur *)zeigeraufchar;
-
ich bins nochmal:
warum funktioniert folgender Code nicht (Zugriffsverletzung beim Ausführen)
void send_message(char id, char typ, char richtung, int x, int y, char spielername[10]) { // Mit dieser Funktion werden Nachrichten versendet nachricht msg; msg.id = id; msg.typ = typ; msg.richtung = richtung; msg.x = x; msg.y = y; strcpy(msg.nickname,spielername); send(s,(char *)&msg,sizeof(nachricht),0); }
void recvstring(nachricht *msg) { // wird bei WM_SOCKET aufgerufen... char *buffer = 0; recv(s,buffer,sizeof(nachricht),0); msg = (nachricht *)buffer; } };
MfG, Rodney
-
hat keiner ne Ahnung?
-
was würde passieren, wenn im buffer den recv() abholt erst ein paar Zeichen stehn würdn und nicht soviele, dass das Struct vollständig übertragen wurde?
Würde das Prog dann abstürzen? Wie bekomme ich raus wieviele bytes im buffer sind bevor ich sie abrufe?
-
buffer hat keinen speicher und du willst was reinschreiben... kann nicht gut gehen.
-
Shade Of Mine schrieb:
buffer hat keinen speicher und du willst was reinschreiben... kann nicht gut gehen.
wie reservier ich denn speicher fürn nen char*, ich arbeite sonst immer nur mit nullt. Char-arrays...
-
char *ChVar; // z.B. für 1024 chars: ChVar = new char[1024]; // aber auch unbedingt Speicher wieder freigeben (wird nicht automatisch //gemacht!!!!!!) delete [] ChVar; // und dannach am besten auf NULL setzten !!! ChVar = NULL;
-
ok, ich reserviere jetzt speicher aber das Prob besteht immer noch...
Das Programm stürztzt in diesen Funktionen ab
-
//Aufrufen z.B. mit // nachricht msg; // hier wird der Speicher reserviert // recvstring( &msg); void recvstring(nachricht *msg) { // wird bei WM_SOCKET aufgerufen... // char *buffer = 0; recv(s, msg, sizeof(nachricht),0); // direkt nach msg schreiben // msg = (nachricht *)buffer; }
-
direkt nach msg schreiben geht ja nicht, weil ich nen Cast brauche...
Sonst meckert jedenfalls der compiler
-
-
Code Strukturen mit folgenden Muster (was du vorschlaegst)
// ... komm von irgendwo { // nu brauch ich ne feste anzahl an SPeicher : char * buffer = new char[1024]; // ... tu irgendwas //nu brauch ich Speicher nimmer delete[] buffer; buffer = NULL; }
Machen ned viel sinn, besser gesagt sind unperformant
besser:// ... komm von irgendwo { // buffer besser statisch anlegen char buffer[1024]; // genu so benutzen wie vorher. }
der statische buffer wird nun auch nur angelegt, wenn in den code-abschnitt kommst ....
dynamisch speicher allokieren solltest du nur wenn :
du mehrere Objecte unbestimmter anzahl allokieren musst (container)
die lebensdauer deiner objecte den scope deiner erzeugenden funktion ueberschreiten (smartpointer) oder die erzeugten objecte unbestimmten Types sind (implementierung verborgen, object - factory usw zaehlen hier rein).
Abhaengigkeiten aufloesen willst (PIMPL idom)Das wars eigentlich schon ....
Sogar polymorhy kann man mit statischen objekten betreiben ... new und delete sind nu mal schweineteuer ....@Rodney
prinzipiell:Du willst streamen, dann benutze auch streams
nim dir nen stl stream her, ueberlade die << >> operatoren fuer deine Klasse ... dann uebertrage den stream, das design duerfte etwas zukunftstraechtiger sein ....nutze keine c-casts ... nim reinterpret_cast wenn mit c++ arbeitest ....
zum copieren auf auf statisch allokierte speicherbereiche nimm strncopy (sicherer)"char spielername[10]" in ner parameterliste ? das funzt ? besser "const char * " und die lanege auch noch als parameter ....
Schreibst du eigentlich c oder c++ ??
Sieht mir so eher nach c aus ...Ciao ...
-
ich schreib eignetlich son ziemliches c/++ gemisch...
Sieht man ja auch am code.Aber prinzipiell müsste es doch auch mit den Funktionen gehen de ich verwendet habe oder??
-
der statische buffer wird nun auch nur angelegt, wenn in den code-abschnitt kommst ....
dynamisch speicher allokieren solltest du nur wenn :
du mehrere Objecte unbestimmter anzahl allokieren musst (container)
die lebensdauer deiner objecte den scope deiner erzeugenden funktion ueberschreiten (smartpointer) oder die erzeugten objecte unbestimmten Types sind (implementierung verborgen, object - factory usw zaehlen hier rein).
Abhaengigkeiten aufloesen willst (PIMPL idom)+Wenn die größe des objekts zu groß für den stack ist.
-
@Otze
... aehm ja , stammel ... , stimmt !ich schreib eignetlich son ziemliches c/++ gemisch...
Das solltest dir aber abgewoehnen ... entweder oder ...
und c++ bringt ned nur nachteile, also nutze auch die vorteilePrinzipiell sollte es so natuerlich auch funzen ...
Aus deinen Namen usw ergibt sich der Verdacht, das das fuer nen Spiel sein soll, also performance ned ganz so unkritisch ....Gute ideee, die daten schon mal als strukt / class ohne pointer zu verwenden, weil sie da so schoen beieeinanderliegen, und man kann sizeof verwenden ....
wenn die rohdaten verschicken ... willst, kommst besser due castest gleich auf void * ....
bei parameteruebergabe kopien vermeiden ....Ich wuerde als erstes den String festnageln, daraus ne feste Stringklasse machen, damit die im Ctor usw, verwenden kannst .. evtl als template , und trotzdem liniear kopieren kannst
dann deine message als klasse ..... mit hintereinander liegenden daten ....
deiner sende funktion natuerlich nur ne (konstante)referenz auf die klasse uebergeben
dann kannst da gemuetlich per sizeof und memcopy die daten hin und herschaufeln ...
ciao ...
-
klar könnte ich das jetzt alles umschreiben, aber eigentlich würd ich gern wissen warum es jetzt nicht geht... Ist doch alles richtig gemacht
void send_message(int timestamp, char id, char typ, char richtung, int x, int y, char spielername[10]) { // Mit dieser Funktion werden Nachrichten versendet nachricht msg; msg.timestamp = timestamp; msg.id = id; msg.typ = typ; msg.richtung = richtung; msg.x = x; msg.y = y; //strcpy(msg.nickname,spielername); char *buffer; buffer = new char[sizeof(nachricht)+1]; buffer = (char *)&msg; send(s,(const char*)buffer,sizeof(nachricht),0); delete[] buffer; buffer = 0; } void recvstring(nachricht *msg) { char *buffer; buffer = new char[sizeof(nachricht)+1]; recv(s,buffer,sizeof(nachricht),0); msg = (nachricht *)buffer; delete [] buffer; buffer = 0; } };
-
void send_message(int timestamp, char id, char typ, char richtung, int x, int y, char spielername[10]) { // Mit dieser Funktion werden Nachrichten versendet nachricht msg; msg.timestamp = timestamp; msg.id = id; msg.typ = typ; msg.richtung = richtung; msg.x = x; msg.y = y; send(s,(const char*)&msg,sizeof(nachricht),0); } void recvstring(nachricht *msg) { recv(s,(const char*)msg,sizeof(nachricht),0); };
ungetestet(arbeite nicht mit sockets), aber sollte funktionieren
-
Pack recv noch in eine Schleife. Dir ist naemlich nicht garantiert, dass alle
Datenpackete in nur einem Segment uebertragen werden. Ansonsten ist der Code
natuerlich ziemlich gefaehrlich, naemlich dann, wenn fuer msg vorher kein Speicher
reserviert worden ist. Das sollte man vielleicht vorher noch pruefen und ggf.
einen Fehlercode zurueckgeben.mfg
v R
-
wie willst du prüfen, ob für msg speicher reserviert wurde? das ist unmöglich, spätestens, wenn das teil mit new erstellt wurde, kannst dus vergessen, oder einen smartpointer verwenden...was im falle eines stack objekts irgendwie eine ziemliche kanone auf nen ärmlichen spatzen wär
najut, recv mit schleife:
int recvstring(nachricht *msg) { WSASetLastError(0); while(recv(s,(const char*)msg,sizeof(nachricht),0)<sizeof(nachricht)){ int error=WSAGetLastError(); if(error){ throw error;//oder irgendwas andres } } };
-
Zumindest ein
if(msg)
koennte man einbauen. Ansonsten knallts halt, aber das ist ja nicht dein Problem.
mfg
v R