【问题标题】:Server with multiple clients using fork()使用 fork() 的具有多个客户端的服务器
【发布时间】:2015-01-07 15:26:04
【问题描述】:

这是我的场景:我的服务器应该同时使用套接字和fork() 处理两个客户端。服务器与两个客户端共享 same int 数组 data[] ,随机获得。如果data[2] 是一个精确的数字,client1 会执行它的工作并将其工作重新发送到服务器,否则 client2 会执行它的工作 ecc。这将继续无限循环,直到服务器端 CTRL+C 信号。 我认为我的问题出在我写的这个服务器 sn-p 上:

//...
while (1) {
  printf("\n*****server waiting for new client connection:*****\n");

  msgsock=accept(sock,(struct sockaddr *)&client,(socklen_t *)&lenght);
  if(msgsock == -1){
    perror("accept");
    exit(-1);}
  pid = fork();
  if (pid == 0){
    do{
      srand((unsigned) time(&t));
      data[0] = rand() %15;
      data[1] = rand() %10;
      data[2] = rand() %2;
      printf("I wrote %d %d %d\n", data[0], data[1], data[2]);
      if(write(msgsock,data,sizeof(data))<0){
        perror("writing message");}
      if(read(msgsock,data2,sizeof(data))<0){ //read the result from client
        perror("reading message");}
      printf("Result is %d\n", data2[3]);} 
      while(1);
    exit(0);}

这一次只适用于一个客户端,一旦我运行第二个客户端,它就会创建一个新的孩子并且只处理较新的客户端。我希望根据每个循环中data[2] 的内容为两个客户端提供服务。 提前致谢。

编辑: 我不能使用共享内存或类似的东西和线程,只能使用套接字和信号量。 fork 的使用只是我试图解决这个练习的一个想法。

【问题讨论】:

  • read(msgsock,data2,sizeof(data)) 看起来很可疑,你不是说sizeof(data2)吗?
  • 如果你想让它在两个分支上运行,if (pid == 0) 有什么意义?
  • 至于你的问题,你可能想用线程来代替?还是共享内存?
  • 我认为你不应该使用exit(0),而是使用_exit(0)。
  • 如果你想分享东西,请考虑不要使用 fork 模型。按照今天的标准,它已经过时了。

标签: c sockets client-server fork


【解决方案1】:

在分叉时,您创建第二个进程,它是原始进程的克隆。这意味着您的流程中的所有数据结构都将被复制。如果您之后在一个进程中修改它们,这些更改将不会在另一个进程中看到。因此,在两个分叉的客户端处理程序之间共享信息将无法通过简单地将值写入数组来实现。您可以为此使用共享内存,但在您的情况下,使用线程或切换到非阻塞 I/O 可能是更好的选择。如果您的练习需要使用fork,您可以使用套接字或管道来帮助分叉的进程进行通信,但这似乎相当复杂。

您还应该知道,默认情况下,在fork() 上,您会复制所有文件描述符。这意味着在第一个分叉上,两个套接字描述符都被克隆了。您要用于处理客户端的子进程将拥有一个不需要的侦听套接字句柄。父级同样将有一个用于客户端连接的打开描述符。在您的孩子中关闭sock,在您的父母中关闭msgsock(其他部分,当pid!= 0时)。此外,您应该通过调用例如清理父级中已完成的子进程。 wait() on SIGCHLD,否则每次客户端断开连接时都会堆积僵尸进程。

最后,建议通过检查errno 正确处理accept()/read()/write() 的返回值EAGAIN 或EINTR,这基本上意味着“重试相同的呼叫”,但您退出(接受),或者只是前进到下一个语句(读/写)。如果您的协议需要交替读取、写入、读取、写入,则其中一个可能会因信号而失败,您会跳过它。因此,您可能会在没有写入的情况下进行另一次读取,但连接的客户端确实需要一些数据,永远等待,永远不会发回任何东西。

【讨论】:

  • 该练习不需要使用fork,它只需要使用套接字(和信号量)并且不共享内存或消息队列。我的问题是我不知道如何同时处理 2 个或更多客户端,在它们之间共享 same 数组。使用fork 只是我的一个想法。
猜你喜欢
  • 2012-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-02
  • 2018-01-04
相关资源
最近更新 更多