2013-11-24 46 views
0

我正在开发一个使用套接字的简单聊天应用程序。它是客户端 - 服务器驱动的。 一切工作完美,除了这个错误,我无法找到:如果我是第一个连接到服务器的客户端,我收到的每一条消息只是在屏幕上打印一次(因为它应该是)。尽管如此,如果我是连接的第二个客户,我收到的每条消息都会打印两次,第三个客户会看到他的消息三次,依此类推。我真的快疯了,因为这样:套接字 - 客户端双面打印

当我通过socket收到的东西,我打印出来是这样的:

printf (" >%s \n", received); 

因此,如果我得到的消息hello,由用户“查尔斯·发送“我打印信息>> charles:hello”,令我感到惊讶的是,重复的照片没有添加的“>”字符(重复的将是“charles:hello”),因此我无法找到在哪里正在进行打印(上面的printf()是我的代码中唯一的printf())。

我会很感激任何帮助。以下是从套接字接收的代码部分:

while (1) { 
    recv(newsockfd, recibido, 255, 0); 
    printf (">%s \n",recibido); 
} 

此代码由线程执行。

谢谢,伙计们。

下面是客户端的全码:

void *Atender(void *estructura){ 
    DATOS *info; 
    info = (DATOS *)estructura; 
    int newsockfd=info->socket; 
    char recibido[255]; 
    memset(recibido,1,255); 
    while (1){ 
     recv(newsockfd, recibido, 255, 0); 
     printf (">%s \n",recibido); 
     memset(recibido,0,255); 
    } 
} 

main(int argc, char *argv[]) { 
    int sockfd; 
    struct sockaddr_in serveraddr; 
    char *server; 
    Hilos = malloc((200)*sizeof(pthread_t)); 

    /* Remember the program name for error messages. */ 
    programname = argv[0]; 

    //Realizo lectura e imprimo para chequear que se leyo todo bien. 
    lectura(argv,argc); 

    /* Who's the server? */ 
    server=host; 


    /* Get the address of the server. */ 
    bzero(&serveraddr, sizeof(serveraddr)); 
    serveraddr.sin_family = AF_INET; 
    serveraddr.sin_addr.s_addr = inet_addr(server); 
    serveraddr.sin_port = htons(atoi(puerto)); 

    /* Open a socket. */ 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
     fatalerror("can't open socket"); 

    /* Connect to the server. */ 
    if (connect(sockfd, (struct sockaddr *) &serveraddr, 
     sizeof(serveraddr)) < 0) 
     fatalerror("can't connect to server"); 

    enviarInfoInicial(sockfd,nombre,"Actual"); 

    char buff[200]; 
    memset(buff,1,200); 


    //Creacion del hilo que se quedara siempre escuchando 
    DATOS d; 
    d.socket=sockfd; 
    pthread_create(&Hilos[iterador_hilos],NULL,Atender,(void *)&d); 
    iterador_hilos++; 

    //El que no es un hilo se queda siempre esperando por si se quiere 
    //introducir un comando 
    while (1) { 
     fgets(buff, sizeof buff, stdin); 
     mandarInstruccion(sockfd,buff); 
     if ((buff[0] == 'f') & (buff[1] == 'u') & (buff[2] == 'e')){ 
      printf("Cchat se ha cerrado. \n"); 
      close(sockfd); 
      exit(0); 
     } 

     memset(buff,1,200); 
    } 
} 

的代码是西班牙语,但总的想法是可以理解的。 DATOS结构只是传递给创建的线程的结构,并且只包含该线程将从中读取的套接字(以前发布的while(1))。 “ATENDER”是线程执行的过程。

下面是来自服务器的相关代码:

void EjecutarInstruccion(char tipo[],char argumento[],char usuario[]) { 
    if (!strcmp(tipo,"men")) { 
     char sala[20]; 
     char total[300]; 
     memset(total,0,300); 
     strcpy(sala,ObtenerSalaUsuario(usuario)); 
     int i=0; 
     for (i;i<200;i++) { 
      if (!strcmp((lusuarios[i].sala),sala)) { 
       strcat(total,usuario); 
       strcat(total,": "); 
       strcat(total,argumento); 
       send (lusuarios[i].socket, total, strlen(total)+1, 0); 
      } 
     } 
    } 
} 

在服务器端,我有用户的数组,每个用户包含自己的用户名,聊天室,他是在和他的插座(的FD)。当服务器需要发送消息时,只有当他在同一个聊天室中时,我才会浏览该用户阵列并将该消息发送给该用户。 谢谢。

+0

如果您希望我们发现错误,您需要发布您的客户端和服务器代码。 – simonc

+0

好的,我现在就添加它 – CDS18

+0

你应该发布相关的服务器代码,因为这可能是发送相同的消息。 – Duck

回答

2

您不检查返回多少字节recv。它不一定读取所有未完成的数据。您可能需要循环读取,直到接收到所有字节。

+0

这是卖家伙。一些缺失的memset。无论如何,谢谢你。 – CDS18

+2

与send()相同。 OP因此忽略'recv()'和'send()'返回的**相关**值。 – alk