这是我的方案:我的服务器应该使用套接字和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
只是我试图解决这个问题的一个想法。
答案 0 :(得分:0)
在分叉时,您创建第二个进程,该进程是原始进程的克隆。这意味着您的流程中的所有数据结构都将被复制。如果之后在一个过程中修改它们,则在其他过程中将看不到这些更改。因此,只需将值写入数组,就无法在两个分离的客户端处理程序之间共享信息。您可以使用共享内存,但在您的情况下,使用线程或切换到非阻塞I / O可能是更好的选择。如果您的练习需要使用fork
,您可以使用套接字或管道来帮助分叉进程进行通信,但这看起来相当复杂。
您还应该知道默认情况下,在fork()
上复制所有文件描述符。这意味着在第一个fork上,克隆了两个套接字描述符。您要用于处理客户端的子进程将具有不需要的侦听套接字句柄。父类同样将具有客户端连接的开放描述符。关闭您孩子的sock
和父母的msgsock
(其他部分,当pid!= 0时)。此外,您应该通过调用例如父进程来清理已完成的子进程。 wait()
上的SIGCHLD
,否则每次客户端断开连接时都会堆积僵尸进程。
最后,建议处理返回值&lt;检查accept()/read()/write()
,errno
正确0。您可能只是获得EAGAIN
或EINTR
,这基本上意味着“重试相同的调用”,而是您拯救(接受),或者只是前进到下一个语句(读/写)。如果您的协议需要更改读,写,读,写,其中一个可能由于信号而失败并且您跳过它。所以你可能在没有写入之间进行另一次读取,但是连接的客户端确实需要一些数据,永远等待,永远不会发回任何内容。