使用fork()的多个客户端的服务器

时间:2015-01-07 15:26:04

标签: c sockets client-server fork

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

//...
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只是我试图解决这个问题的一个想法。

1 个答案:

答案 0 :(得分:0)

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

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

最后,建议处理返回值&lt;检查accept()/read()/write()errno正确0。您可能只是获得EAGAINEINTR,这基本上意味着“重试相同的调用”,而是您拯救(接受),或者只是前进到下一个语句(读/写)。如果您的协议需要更改读,写,读,写,其中一个可能由于信号而失败并且您跳过它。所以你可能在没有写入之间进行另一次读取,但是连接的客户端确实需要一些数据,永远等待,永远不会发回任何内容。