Struct per Netzwerk übertragen



  • 😕



  • könnte vielleicht jemand einmal einen kleinen Codeauschnittgeben wie ich das ganze erstmal in char herein und dann wieder herauscasten kann?

    struct meinestruktur {
        int x;
        int y;
        char name[50];
        int richtung;
    }
    


  • 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



  • 😕



  • @Kingrabbit

    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 !

    @Rodney

    ich schreib eignetlich son ziemliches c/++ gemisch...

    Das solltest dir aber abgewoehnen ... entweder oder ...
    und c++ bringt ned nur nachteile, also nutze auch die vorteile 🙂

    Prinzipiell 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


Anmelden zum Antworten