【问题标题】:Unable to send message received by one client to all other clients connected to the server无法将一个客户端收到的消息发送到连接到服务器的所有其他客户端
【发布时间】:2016-08-08 18:09:46
【问题描述】:

我正在做一个与 C 中的网络编程相关的小项目。我试图制作一个简单的群聊程序,其中多个客户端同时连接到单个服务器,并且每当任何客户端写入消息时,服务器将向所有其他客户端发送该消息。

简而言之,它是一个群聊,所有连接到服务器的客户端都可以相互通信。但是,我遇到了一个我无法弄清楚的奇怪问题。

我正在做的是:运行服务器 -> 运行客户端 1 -> 运行客户端 2 -> 运行客户端 3 -> 现在当客户端 1 键入消息时,没有其他客户端接收该消息 -> 当客户端 2 键入消息,只有客户端 1 收到该消息 -> 当客户端 3 键入消息时,客户端 1 和客户端 2 都会收到该消息。

出于某种奇怪的原因,它的工作方式是客户端的消息只会发送到在该客户端之前连接到服务器的那些客户端。由于客户端 3 在 1 和 2 之后连接,因此 1 和 2 收到了第三个客户端的消息,但是第三个客户端没有收到第二个客户端的任何消息。

以下是我在 server.c 文件中使用的代码:

    comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
    arr[count++] = comm_fd;
    printf("Client %d connected to the server!\n",comm_fd);
    if ( (childpid = fork ()) == 0 ) { /*0 means child process*/
        do {
        read(comm_fd,recvline,100);
        printf("Client %d: %s",comm_fd,recvline);
        if(strcmp(sendline,"bye\n") == 0) {
          printf("Client %d left the chat!\n",comm_fd);
          close(comm_fd);
          exit(4);
        }
        for(int i=0; i<count; i++){
          if(arr[i]!=comm_fd) {
            write(arr[i],recvline,strlen(recvline)+1);
          }
        }
      } while(1);
    }

这是我的client.c:

  fgets(sendline,100,stdin);
  write(sockfd,sendline,strlen(sendline)+1);
  if(strcmp(sendline,"bye\n") == 0) {
    printf("Closing connection!\n");
    exit(4);
  }
  bzero( sendline, 100);
  if ( (childpid = fork ()) == 0 ) {
    do{
      read(sockfd,recvline,100);
      printf("%s",recvline);
      if(strcmp(recvline,"bye\n") == 0) {
        printf("\nA client left the chat group!\n\n");
        exit(4);
      }
      bzero( recvline, 100);
    } while(1);
  }

谁能帮我解决这个问题?我搜索了很多解决此问题的方法,但找不到答案。我是套接字编程的新手,所以我真的需要帮助。提前致谢!

【问题讨论】:

  • fork() 可能是此类服务器的错误型号。每次接受新连接并派生一个新子节点时,请考虑arr[] 数组的状态。

标签: c sockets tcp network-programming


【解决方案1】:

出于某种奇怪的原因,它的工作方式是通过 客户端只会被发送到那些连接到服务器的客户端 在这个客户之前

这种行为对我来说很有意义——fork() 创建了一个子进程,其内存/状态是父进程当前状态的副本,这意味着对父进程的任何更改(例如接受在 fork() 调用之后发生的新客户端连接)不会传播到现有的子进程。因此,每个子进程将仅“看到”在通过 fork() 创建自己的子进程时已经连接的客户端。

【讨论】:

  • 对我来说也很有意义(Y)有没有办法更新对分叉子进程的更改?
  • 当然,您可以通过它的标准输入文件描述符,或者通过套接字或管道或诸如此类的方式与它通信。不过,我同意 keithmo 的评论,这种事情在单个进程中(例如通过 select() 事件循环或通过多线程)比通过多进程和 fork() 更容易和简单地实现。进程空间分离对你不利,并没有给你带来太多好处。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-15
  • 2013-04-01
  • 2023-04-08
  • 2015-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多