用ncurses,套接字和fork绘图

Dav*_*nos 1 c sockets fork

所以我正在做理发店问题,但现在我想让它"视觉化"和网络友好.当服务器启动时,等待客户端连接,每次客户端连接时都会绘制一个"P",它在屏幕上传播到理发位置.我和NCurses这样做,我没有问题.

但是我一次只设法绘制一个客户端(一个'P').我想在屏幕上看到很多客户端('P').因为我现在拥有它的方式我一次只使用1把椅子,然后客户端被出席并退出,然后accept()队列中的下一个客户端进入屏幕,依此类推.它给人的印象是没有实际的共识.

我有一个非常宽松的代码但叉/插座部分在这里:

pid_t client;
int p;
RandSeed=8;
 listen(connection,90);
 while(1){
     remote_dir_size = sizeof(remote_dir);
    //"Awaiting connection...
     if((connection_client=accept(connection,(struct sockaddr *)&remote_dir,&remote_dir_size))<0){
         console_write("CONNECTION REJECTED!");
         exit(-1);
     }
    //"Connection accepted!
     client=fork();
     switch(client)
     {
         case -1:
            console_write("Error Forking!!");
            exit(1);
         case 0:
            close(connection); //So that another client can come.
            recvs = recv(connection_client,petition,sizeof(petition),0);

             //console_write(petition);
            // console_write(" moviendose.");
             move_client();

             //Check for avialable chairs

             //waiting_client_count++;
             sem_wait(waitingRoom); //wait until available
             move_client_to_chairs();
             sitting_client_count++;                
             redraw_chairs();  //redraw chair <--Useless since only 1 chair is used at a time :/
             //waiting for barber

             sem_wait(barberChair);

             //barber available, chair occupied is now free
             sem_post(waitingRoom);
             sitting_client_count--;
             redraw_chairs();

             move_client_to_barber(); //Move 'P' towards barber chair
             sit_client_barber();
             //Wake barber
             sem_post(barberPillow);

             //Wait until barber ends

             sem_wait(seatBelt);
             //release chair
             sem_post(barberChair);
             exit_client();

             exit(0);
         default:

            //barber sleeps until someone wakes him

            sem_wait(barberPillow);
            randwait(5);
            //barber cutting hair
            randwait(5);
            //barber finished
            //free client
            sem_post(seatBelt);
            wait(&p);        
     }
}
Run Code Online (Sandbox Code Playgroud)

代码的完整版本在这里

我的问题是:服务器启动良好.然后,当我运行./client服务器屏幕开始P沿着屏幕绘制并且它正确地移动它,客户端得到它的理发并退出.但是,当我运行2个或更多时./client,服务器屏幕一次绘制一个进程,理发店内一次只有一个客户端; 好像它正在等待那个客户端exit()才能启动下一个forked过程.

我觉得这很奇怪,我在这里错过了什么?这是accept排队的问题吗?我应该尝试不同的观点吗?

Las*_*lko 5

问题是你的父进程正在尝试做两件需要等待的事情:

  • "理发师睡觉直到有人叫醒他"

  • accept()

没有某种联合等待,这种架构不起作用.两段代码都在等待一种事件,而忽略了其他类型的事件.例如,当客户端进入时,程序将不会接受另一个客户端,直到"理发师完成".

解决问题有两个方向:

  1. 加入两种等待:for accept(),你可以将套接字转为非阻塞模式,并使用select()poll()等到事件进入,对于信号量,这不是那么简单,但如果你在父进程之间打开一个套接字和每个孩子,并将信号量处理转换为网络通信,你可以在一个地方单独select()poll()等待所有套接字(一个用于接收新的客户端连接,一个用于与它们通信).您还必须重新设计信号量处理 - 并在那里摆脱睡眠,例如保留活动计时器列表,然后返回select()poll()直到下一个计时器超时(它们的最后一个参数可以限制最大值)等待时间).
  2. accept()信号量处理和信号量处理分成两个进程,即父进程处理新的传入连接,子进程"模拟"理发器.实际上,你尝试实施"理发师"的方式,每个理发师需要一个子进程,因为进程在模拟理发师完成的工作时正在休眠.或者你重新设计了第一部分中提到的"理发师"模拟.