Verwirrung um winsock mit struct und pointer



  • Hallo,

    ich bin ein bisschen verwirrt bezüglich der Winsock Kommunikation und dem Speichern bzw. Lesen der Daten in bzw aus einer Struktur.

    Ich habe eine data.h mit den zwei Strukturen:

    data.h

    ...
    struct request {
    	unsigned char  ReqType;	
    #define ReqNone 0
    #define ReqBook 'B'
    #define ReqStorn 'S'
    	unsigned       FlNr;	/* Flight Number */
    	unsigned       SeNr;	/* Seat Number (== 0) no Special Seat */
    	char           name[32];
    	struct ExpSeat SeatWanted;	/* Type of Seat wanted */
    };
    
    struct answer {
            unsigned char AnswType;
    #define AnswNone 0
    #define AnswOk   'O'
    #define AnswWarn 'W'	/* example: Seat not available */
    #define AnswErr  0xFF
    	unsigned       FlNr;
    	unsigned   SeNo;
    #define ErrNo SeNo	/* Are identical */
    };
    

    Weiterhin habe ich in der Server Datei folgendes

    server.c

    #include <data.h>
    ...
    //Prototypen
    static struct request req;
    ...
    struct request *getRequest() {
      ...
      long rc; 
      // Verbindung annehmen
      rc=accept(s,NULL,NULL);
      while (1){
    // Warte am Socket auf Daten und speichere sie in req ab
        recv(s,(char *)&req, sizeof(struct request), 0);
       {
          printf ("error recvfrom");
          return(0);
        };
          return(&req);
      }
    };
    
    int sendAnswer(struct answer *answ) {
    // Schreibe die uebergebene Antwort answ an das Socket ***/
     send(s,(char *)&answ,sizeof(struct answer),0);
     return(1);
    };
    

    und in der Client Daten folgendes:

    client.c

    #include <data.h>;
    ...
    //Prototypen
    static struct answer answ;
    ...
    struct answer *DoRequest(struct request *req) {
    ...
    // Schreibe in das Socket die Anfrage req 
      send(s,(char *)&req,sizeof(struct request),0);
      while (1){
    // Lese die Antwort vom Socket und speichere sie in answ ab 
        recv(s,(char *)&answ,sizeof(struct answer),0);
        {
         printf ("error recvfrom");
         return(0);
        };
       break;
      }
    //schließe Socket
      closesocket(s);
      return(&answ);
    };
    

    Der Compiler läuft ohne Probleme durch und ich kann den Server (server.exe) starten. Winsock wird gestartet, der Socket wird erstellt und an den Port gebunden und er geht in den listen Mode.
    Wenn ich dann aber den Client starte wird bei ihm auch Winsock gestartet, der Socket erstellt und er verbindet sich mit dem Server.
    Sofort danach bekomme ich vom Debugger die Fehlermeldung: Unbehandelte Ausnahme bei 0x0042ed11 in server.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000.

    Ich denke das irgendwas mit dem recv(..) und dem send(..) und dem speichern/lesen aus der Structur nicht funktioniert. Ich sehe leider nicht was!

    Hat jemand eine Ahnung?

    Danke,

    Andreas



  • Versuche mal mit Debuggen heraus zu finden wo das passiert.
    Außerdem sieht das sehr stark nach reinem C aus.

    mfg.



  • Hi !

    Die Funktion send hätte gern als zweiten Paramter den Typ:
    const char FAR * buf,
    und die Funktion recv gibt sich mit einem char FAR * buf zufrieden.
    Weil deine Parameter vom Typ static struct und als char* gecastet sind, geht das schief.

    Edit: Um in der Zeile 13 einen Namen empfangen zu können, müsste der Aufruf so aussehen:
    recv(s, req.name, sizeof(req.name), 0);

    Gruß,
    p.



  • Hallo,

    danke erstmal für die Antworten.
    Wie kann ich es bewerkstelligen das der ganze Inhalt der Struktur empfangen wird und nicht nur der Name?

    Dnake,

    Andreas



  • Für die komplette Struktur kannst du es mit deiner cast- Methode machen,
    wenn du für genug Puffer sorgst.

    Der dritte Parameter in deiner recv Funktion z.B. berücksichtigt nicht, das in der Struktur struct request noch eine weitere Struktur enthalten ist, nämlich
    struct ExpSeat.

    Darum müsstest du den dritten Parameter erweitern:
    ... ,sizeof(struct request) + sizeof( struct ExpSeat ), ; ...

    Die defines kannst du aus deinen Strukturen rausschmeissen und global definieren, weil sie sich nicht kapseln lassen und auch nicht übertragen werden.
    Sie haben keinen Einfluss auf die Größe der Strukturen.

    Grüße,
    p.



  • proggingmania schrieb:

    Hi !

    Die Funktion send hätte gern als zweiten Paramter den Typ:
    const char FAR * buf,
    und die Funktion recv gibt sich mit einem char FAR * buf zufrieden.
    Weil deine Parameter vom Typ static struct und als char* gecastet sind, geht das schief.

    static heisst hier: nur in dieser Uebersetzungseinheit sichtbar, d. h. auf req
    kann nicht aus anderen Uebersetzungseinheiten aus zugegriffen werden.

    Edit: Um in der Zeile 13 einen Namen empfangen zu können, müsste der Aufruf so aussehen:
    recv(s, req.name, sizeof(req.name), 0);

    Er sendet aber die ganze Struktur 'request'. Was will er dann mit mit Daten
    in 'name'?

    proggingmania schrieb:

    Für die komplette Struktur kannst du es mit deiner cast- Methode machen,
    wenn du für genug Puffer sorgst.

    Er hat ja genug Puffer, denn er hat ja eine Instanz von req erzeugt.

    Der dritte Parameter in deiner recv Funktion z.B. berücksichtigt nicht, das in der Struktur struct request noch eine weitere Struktur enthalten ist, nämlich
    struct ExpSeat.

    Darum müsstest du den dritten Parameter erweitern:
    ... ,sizeof(struct request) + sizeof( struct ExpSeat ), ; ...

    Nein das musst du natuerlich nicht. Die Groesse innerer Strukturen wird korrekt
    in die Berechnung mit einbezogen. Dieses Problem haettest du nur, wenn
    SeatWanted ein Zeiger waere.

    Die defines kannst du aus deinen Strukturen rausschmeissen und global definieren, weil sie sich nicht kapseln lassen und auch nicht übertragen werden.
    Sie haben keinen Einfluss auf die Größe der Strukturen.

    Definiere "uebertragen werden". Ansonsten ist es natuerlich korrekt. Aber man
    "sieht" hiermit eine gewisse Zugehoerigkeit der Defines. Allerdings nur, wenn
    man sich die Deklaration anschaut, im Quellcode selber geht sie verloren.

    while (1){
    // Warte am Socket auf Daten und speichere sie in req ab
        recv(s,(char *)&req, sizeof(struct request), 0);
       {
          printf ("error recvfrom");
          return(0);
        };
          return(&req);
      }
    

    Schau dir den Code mal genau an. Wann geht er in den inneren Block rein und
    was gibt er in diesem Falle zurueck? Was passiert danach mit dem Rueckgabewert?
    Versuchst du auf diesen zuzugreifen? In client.c tust du das uebrigens auch.
    Sieht nach einer vergessenen if-Bedingung aus.

    Lass den Code mal im Debug-Modus laufen und mach einen Backtrace.

    gruss
    v R



  • virtuell Realisticer schrieb:

    Nein das musst du natuerlich nicht. Die Groesse innerer Strukturen wird korrekt
    in die Berechnung mit einbezogen. Dieses Problem haettest du nur, wenn
    SeatWanted ein Zeiger waere.

    Ja, stimmt, sorry.
    Die Zeile

    recv(s,(char *)&req, sizeof(struct request), 0);
    

    ist also durchaus korrekt.


Anmelden zum Antworten