recv()/send() und \0



  • Hi,
    Ich hab ein Client/Server Programm das "rohe" Daten übertragen soll.
    Das Problem ist, dass in den zu übertragenden Daten auch ab unz zu 0en vorkommen.
    Allerdings wird sobald recv() eine 0 erhält das weitere Empfangen abgebrochen (kein Fehler, sondern der restliche buffer ist einfach leer).
    Weiß jemand wie ich das beheben kann??

    LG



  • Socketer schrieb:

    Allerdings wird sobald recv() eine 0 erhält das weitere Empfangen abgebrochen (kein Fehler, sondern der restliche buffer ist einfach leer).

    Nein, da musst du irgendwas falsch interpretieren. recv empfängt genau die angegebene Zahl von Bytes, egal was drin ist.



  • hmm bei mir nicht:
    Ich verwende den Tcp-Server und Client von da:
    http://www.cs.binghamton.edu/~nael/cs528/tutorial/

    und wenn ich in tcp-client.cc die nachricht so verändere:
    char msg[80] = "Hello Wo\0rld!";
    dann kommt zurück:
    8 bytes: Hello Wo

    LG



  • Du kannst hier nicht strlen() benutzen, um die Länge des Strings herauszufinden. Strings sind in C schließlich Null-terminiert, also hört strlen() dort auf zu zählen. Die tatsächliche Länge der empfangenen Daten bekommst du als Rückgabewert von recv().



  • Daran hatte ich natürlich auch gedacht.
    Ich verwende strlen nicht sondern übergebe die Größe.

    LG



  • Nimmst du auch auf dem Server kein strlen? Zeig mal ein _minimalen_ Beispiel, dass dein Problem illustriert. Es wird definitiv irgend wie an deinem Code liegen (hast du zB beim Server noch das strlen drin?)



  • Nein eigentlich nicht:
    Server:

    /* stream server: echo what is received from client */  
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    int main (int argc, char *argv[])
    {
      int s, t;
      int recvd;
      unsigned int sinlen;
      struct sockaddr_in sin;
      char msg[80];
    
    if (argc < 2) { 
        printf ("%s port\n", argv[0] ); /* input error: need port no! */
       return -1;
    }
    
    //first create a TCP socket
    if ( (s = socket(AF_INET, SOCK_STREAM, 0 ) ) < 0) { /* create socket*/
      perror("socket");  /* socket error */
      return -1;
    }
    
    sin.sin_family = AF_INET;              /*set protocol family to Internet */
    sin.sin_port = htons(atoi(argv[1]));  /* set port no. */
    sin.sin_addr.s_addr  = INADDR_ANY;   /* set IP addr to any interface */
    
    //then bind it to my address and specified port num
    if (bind(s, (struct sockaddr *)&sin, sizeof(sin) ) < 0 ){
         perror("bind"); return -1;  /* bind error */
    }
    
    /* server indicates it's ready, max. listen queue is 5 */
    if (listen(s, 5)) { 
        perror ("listen"); /* listen error*/
       return -1;
    }
    
    sinlen = sizeof(sin);
    while (1) {
    	/* accepting new connection request from client,
      	socket id for the new connection is returned in t */
    	if ( (t = accept(s, (struct sockaddr *) &sin, &sinlen) ) < 0 ){
      		perror("accept ");  /* accpet error */
      		return -1;
    	}
    	printf( "From %s:%d.\n",
               	inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) );
    	if ( recvd = recv(t, msg, sizeof(msg),0 ) <0) {  /* read message from client */
         		perror("recv");         /*  recv error */
         		return -1;
    	}
    	printf("Read %s\n",msg);
    	if ( send(t, msg, recvd,0 ) < 0 ) {  /* echo message back */
           	perror("send");    return -1; /*  send error */
    	}
    	/* close connection, clean up sockets */
    	if (close(t) < 0) { perror("close"); return -1;} 
    } // will never reach below
    
    if (close(s) < 0) { perror("close"); return -1;}
    return 0;
    }
    

    Client:

    /* stream client: send a message to server */
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <netdb.h>
    
    int main (int argc, char *argv[] )
    {
      int s, n;
      struct sockaddr_in sin; struct hostent *hptr;
      char msg[80] = "Hello Wo\0rld!";
    if ( argc < 3 ) {
          printf ( "%s host port\n", argv[0] );   /* input error: need host & port */
          return -1;
    }
    if ( (s = socket(AF_INET, SOCK_STREAM, 0 ) ) < 0) { /* create socket*/
      perror("socket");  /* socket error */
      return -1;
    }
    sin.sin_family = AF_INET;              /*set protocol family to Internet */
    sin.sin_port = htons(atoi(argv[2]));  /* set port no. */
    if ( (hptr =  gethostbyname(argv[1]) ) == NULL){
           fprintf(stderr, "gethostname error: %s", argv[1]);
           return  -1;
     }
    memcpy( &sin.sin_addr, hptr->h_addr, hptr->h_length);
    if (connect (s, (struct sockaddr *)&sin, sizeof(sin) ) < 0 ){
         perror("connect"); return -1;   /* connect error */
    }
    if ( send(s, msg, 14,0) < 0 ) {  /* send message to server */
           perror("write");    return -1; /*  write error */
    }
    if ( ( n = recv(s, msg, sizeof(msg),0 ) ) <0) {  /* read message from server */
         perror("read"); return -1; /*  read error */
    }
    printf (" %d bytes: %s\n", n, msg);  /* print message to screen */
    /* close connection, clean up socket */
    if (close(s) < 0) { 
       perror("close");   /* close error */
       return -1;}
    return 0;
    }
    


  • if ( recvd = recv(t, msg, sizeof(msg),0 ) <0) {
    

    stimmt natürlcih so nicht. kann es sein, dass es an der ausgabe liegt die nach der 0 abschneidet??



  • Scheint Tatsächlich so zu sein.
    mit gdb erhalte ich: `(gdb) print msg

    $1 = "Hello Wo\000rld!\000\000\000\030v\376\267\001\000\000\000\000\000\000\000\001\000\000\000\250\363...."

    `

    Wenn mir jetzt noch einer sagen könnte wie ich das trozdem auf die Konsole bringe...

    LG



  • fwrite(msg,1,n,stdout)
    

    so evtl?



  • Socketer schrieb:

    printf("Read %s\n",msg);
    

    Im Beispiel liegt da der Hund begraben. Das printf mit Format %s gibt einen nullterminierten String aus. Also den Speicherbereich, auf den msg zeigt bis zum ersten 0-Byte.

    Probier mal das:

    for (i = 0; i < recvd; ++i)
      putchar(isprint(msg[i]) ? msg[i] : '.');
    }
    


  • tntnet schrieb:

    Socketer schrieb:

    printf("Read %s\n",msg);
    

    Im Beispiel liegt da der Hund begraben. Das printf mit Format %s gibt einen nullterminierten String aus. Also den Speicherbereich, auf den msg zeigt bis zum ersten 0-Byte.

    Probier mal das:

    for (i = 0; i < recvd; ++i)
      putchar(isprint(msg[i]) ? msg[i] : '.');
    }
    

    das bringt aber probleme falls das programm die ausgabe in z.b. eine datei umleitet 😉

    lg lolo


Anmelden zum Antworten