recv()/send() und \0



  • 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