2010-03-01 11 views
10

EDIT: el código de abajo es fija para recibir y enviar adecuadamente y dar cuenta de los bytes de mensajes enviados annd recibamos (por último gracias a EJP)zócalo de programación: recv/problema de lectura de

estoy programando con C en Unix.

Tengo el servidor y el cliente que se supone que intercambian mensajes. Mientras que el cliente parece enviar mensajes correctamente, el servidor no recibe los mensajes que envía el cliente. He intentado usar recv() y read() (sé que son prácticamente lo mismo, pero con banderas adicionales en recv()) pero no tengo suerte y no estoy realmente seguro de cuál es el problema realmente.

Pongo sleep(3) en el código del cliente después de cada vez que envía un mensaje, pero veo que una vez que el cliente y el servidor están conectados, el servidor se cierra inmediatamente sin esperar los mensajes entrantes. ¿Qué estoy haciendo mal?

Este es el código del lado del cliente:

#define SERVER_TCP_PORT 11112 
#define MAX_DATA_SIZE 500 

int main(int argc, char * argv[]) 
{ 
    int sockfd; 
    char * host; 
    char msg[MAX_DATA_SIZE];/* = "get my msg!\n";*/ 
    int msg_len; 

    struct hostent * hp; 
    struct sockaddr_in client_address, server_address; 


    printf("y halo thar\n"); 


    // looking up from the host database 
    if (argc == 2) 
     host = argv[1]; 
    else 
     exit(1); 
    printf("sdf\n"); 


    hp = gethostbyname(host); 
    if (!hp) 
     exit(1); 
    printf("host found\n"); 


    // setting up address and port structure information 
    bzero((char *) &server_address, sizeof(server_address)); // copy zeroes into string 
    server_address.sin_family = AF_INET; 
    bcopy(hp->h_addr, (char *) &server_address.sin_addr, hp->h_length); 
    server_address.sin_port = htons(SERVER_TCP_PORT); 
    printf("set\n"); 


    // opening up socket 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
     exit(1); 
    printf("opened\n"); 


    // connecting 
    if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) 
     exit(1); 
    printf("connected\n"); 


    int i; 

    for (i = 0; i < MAX_DATA_SIZE; ++i) 
    { 
     msg[i] = '.'; 
    } 

    msg[MAX_DATA_SIZE-1] = '\0'; 

    for(i = 0; i < 11; i++) 
    { 
     // send message to connected socket 
     msg_len = write(sockfd, msg, MAX_DATA_SIZE); 
     if(msg_len < 1) 
      printf("notsent\n"); 
     else 
      printf("%i bytes sent\n", msg_len); 

     // recieve messages from connected socket 
     msg_len = read(sockfd, msg, MAX_DATA_SIZE); 
     if (msg_len < 1) 
      printf("not recieved\n"); 
     else 
     { 
      printf("%i bytes received\n", msg_len); 
      printf(msg); 
      printf("\n"); 

     } 
    } 


    // close connection 
    close(sockfd); 
    printf("closed\n"); 

} 

y este es el lado del servidor

#define SERVER_TCP_PORT 11112 
#define MAX_DATA_SIZE 500 


int main() 
{ 

    printf("o halo thar\n"); 

    int sockfd, new_sockfd; 
    int client_addr_len; 
    char msg [MAX_DATA_SIZE]; 
    int msg_len; 
    char got_msg [11] = "got ur msg\0"; 
    struct sockaddr_in server_address, client_address; 


    // setting up address and port structure information 
    bzero((char *) &server_address, sizeof(server_address)); // copy zeroes into string 
    server_address.sin_family = AF_INET; 
    server_address.sin_addr.s_addr = htonl(INADDR_ANY); 
    server_address.sin_port = htons(SERVER_TCP_PORT); 


    // opening up socket 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
     exit(1); 
    printf("socket is opened\n"); 


    // binding 
    if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) 
     exit(1); 
    printf("socket is bound\n"); 


    // listening 
    listen(sockfd,5); 
    printf("listening\n"); 

    // block and wait for an incoming connection 

    client_addr_len = sizeof(client_address); 
    new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len); 
    if (new_sockfd < 0) 
     exit(1); 

    printf("accepted\n"); 


    int i; 

    for(i = 0; i < 11; i++) 
    { 
     // recieve messages from connected socket 
     printf("waiting\n"); 
     msg_len = read(new_sockfd, msg, MAX_DATA_SIZE); 
     if (msg_len < 1) 
     { 
      printf("no msg recieved\n");  
     } 
     else 
     { 
      printf("bytes recieved: %i\n", msg_len); 
     } 


     // send message to connected socket 
     msg_len = write(new_sockfd, got_msg, sizeof(got_msg)); 
     if (msg_len < 1) 
      printf("not sent\n"); 
     else 
      printf("%i bytes sent\n", msg_len); 
    } 


    // close connection 
    close(sockfd); 
    printf("socket closed. BYE! \n"); 


} 

Respuesta

10

En el código del servidor, el problema está en esta línea:

msg_len = read(sockfd, msg, MAX_DATA_SIZE); 

Usted está llamando read en sockfd, pero hay que llamar read o recv en new_sockfd (el socket devuelto por accept()). new_sockfd es el que está conectado al cliente (sockfd se usa para aceptar conexiones adicionales, por ejemplo, si otro cliente se conecta).

+0

¡Gracias que resolvió el problema! Y sí, tiene mucho más sentido leer el nuevo descriptor de archivo de socket de accept(). –

+2

También está ignorando los recuentos devueltos por read() y write() además de buscar errores. No puede hacer eso: debe usarlos para determinar la cantidad de datos que realmente se leyeron o escribieron. No puede asumir que su solicitud se haya completado por completo. – EJP

+0

EJP el código ahora cuenta para los bytes reales de msgs enviados y recibidos. Gracias. –

-1

se basa la aplicación en funcionamiento o datagrama?

existen algunos problemas con el flujo de operación. el servidor puede comenzar a leer antes de que el cliente envíe algo.

dado que el cliente y el servidor están separados, puede imaginarlos ejecutándose simultáneamente. justo después de que su servidor "acepte" la solicitud de conexión, es posible que se produzca una sobrecarga o demoras en la red que provocan que la aplicación del servidor se ejecute antes, intente extraer datos pero encuentre errores (aún no se han recibido datos). puede probar esto agregando reposo en el código del servidor después de aceptar la conexión, donde el cliente debe tener tiempo suficiente para enviar los datos.

Otra mejor solución es hacer frente a la recuperación de datos con el búfer vacío o la lectura asíncrona.

+0

No hay ningún problema en absoluto con el servidor llamando 'read' antes de que el cliente envía nada. La llamada 'lectura' simplemente bloqueará hasta que los datos estén disponibles. "No se han recibido datos todavía" es ** no ** un error. – caf

+0

Y tampoco hay necesidad de dormir. – EJP

+0

Solo agregué sleep() en el lado del cliente para localizar cuál era el problema, pero realmente no puedo (y no debería tener que) usar sleep() ya que el propósito de este programa es medir viajes de ida y vuelta. –

0

Debe leer del zócalo devuelto por accept.

Intente llamar read en el socket devuelto desde accept.

+0

El mensaje enviado por el cliente comienza claramente con un carácter ''.''. – caf

+0

oh, estaba buscando una parte incorrecta del código – stefanB

0

Enviar lateral:

while(!feof(fp)) 
{ 
    len=fread(buff,sizeof(char),MW,fp); 
    if(len==0) 
    { 
     //EOF 
     st=write(cd,&d,sizeof(int));  
     break; 
    } 
    else 
    { 
     st=write(cd,buff,len); 
    } 
} 
0

receptor lateral:

while(1) 
    {  
     len=read(sd,buff,sizeof(buff)); 

     if(len==0) 
     { 
      //End of File receving.    

      break; 
     } 
     else  
     { 
      st=fwrite(buff,sizeof(char),len,fp); 

     } 
    } 
Cuestiones relacionadas