c - Sockets-客户端双重打印

标签 c sockets client-server chat

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

当我通过套接字接收到一些东西时,我会像这样打印它:

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

因此,如果我收到消息 hello,由用户“charles”发送,我会打印消息“>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)。当服务器需要发送消息时,我会遍历用户数组并仅当他在同一个聊天室时才将消息发送给该用户。 谢谢。

最佳答案

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

关于c - Sockets-客户端双重打印,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20177555/

相关文章:

c - 检测文件中的字符并在C中分割字节数组

java - 如何发现监听端口 x 的 IP 地址

tcp - 谁首先在客户端-服务器连接中设置 tcp FIN 标志

c - 在 C 的 header 中使用 "#define"

c++ - 在 C 程序中使用单个 C++ 类的最佳方式

linux - 哪种双栈服务器方法更好?

ruby - Ruby在recv时检测套接字关闭

java - 在使用 java 的客户端服务器的 Protocol Buffer 中需要帮助

c# - 将 Sage Line 50 与 Windows 应用程序集成

c - 使用 MinGW 的 GCC 内联汇编加载 IDT 结构失败