我正在尝试编写一个程序,使用服务器和客户端两个进程模拟服务器和客户端之间的通信:
我们将首先启动服务器,然后启动客户端(使用参数/client[server PID][Message]
),我可以只使用UNIX信号向服务器发送字符串消息,因此我使用两个信号SIGUSR1
和SIGUSR2
以二进制形式发送字符值,然后在服务器中将其转换回char并显示:下面是我的客户机代码:
\include<;minitalk_client.h>;
void将消息发送到服务器(pid\u t ppid,const unsigned char*msg)
{
无符号字符掩码;
int i;
ft_putstr(“发送消息”);
ft_putstr((const char*)msg);
ft_putstr(“to server:”);
ft_putnbr(ppid);
ft_putchar('\n');
while(*msg)
{
遮罩=1<;<;7;
while(面具)
{
如果(*消息和掩码)
kill(ppid,SIGUSR1);
其他的
kill(ppid,SIGUSR2);
usleep(300);
面罩>;>;=1;
}
msg++;
}
i=-1;
而(++i<;8)
{
kill(ppid,SIGUSR2);
usleep(300);
}
}
int main(int argc,字符**argv)
{
int-ppid;
如果(argc!=3)
{
写入(2,“无效参数”\n“18);
申报表(1);
}
ppid=ft_原子(argv[1]);
将消息发送到服务器(ppid,(const unsigned char*)argv[2]);
返回(0);
}
和服务器:
\include<;minitalk_server.h>;
无效信号处理器(int sig)
{
静态无符号字符;
静态无符号字符掩码=1<;<;7;
静态布尔值为新消息=true;
如果(是新消息)
{
ft_putstr(“收到来自客户的消息:”);
is_new_message=false;
}
if(sig==SIGUSR1)
字符|=掩码;
面罩>;>;=1;
如果(!掩码)
{
如果(字符)
ft_putchar(字符);
其他的
{
ft_putchar('\n');
is_new_message=true;
}
字符=0;
遮罩=1<;<;7;
}
}
内部主(空)
{
结构动作法;
常数pid_t pid=getpid();
sigemptyset(和act.sa_面具);
act.sa_handler=sig_handler;
sigaction(SIGUSR1和act,0);
sigaction(SIGUSR2和act,0);
ft_putstr(“启动了带pid的minitalk服务器”);
ft_putnbr(pid);
ft_putchar('\n');
而(1)
暂停();
返回(0);
}
因此,我的代码可以正常工作,但我在睡眠
方面有一个问题,当我没有等待足够的时间时,某些信号不会被捕获,它会执行以下操作:
连续暂停会议�@������\@����@����@��������@�����\@��������@������@����@��@���������@������\@�����@���@������@���������十、
我不想等太久,因为这会使我的程序太慢,所以有没有办法把信号输入到;“排队”;所以当我想在一个循环中发送多个信号时,不需要在每个信号之间等待
(我知道信号不是最好的方法,但这是一个学校项目,我只被允许这么做)
自
我不想等太久,因为这会让我的程序太慢
,这样问是有道理的
有没有办法把信号放在;“排队”;所以当我想在一个循环中发送多个信号时,不需要在每个信号之间等待
。但实际上没有,SIGUSR1
,SIGUSR2
,其他普通信号不排队。因此,不仅每次最多只能有一个挂起,而且如果同时有SIGUSR1
和SIGUSR2
挂起,那么它们的交付顺序是未指定的,并且可能与客户提出它们的顺序不同
但可能还有另一种方法可以加速交互并使其更加可靠,同时仍然只依赖信号进行通信。通过在注册处理程序时设置SA_SIGINFO
标志,可以使用接受三个参数的处理程序,第二个参数是指向SIGINFO_t
的指针,该结构包含有关信号的信息。该信息包括发送该信息的进程的PID。您可以使用它使服务器通过向客户端发送信号来确认收到每个信号。然后,客户端将在发送下一个信号之前等待每个信号的确认
服务器将执行以下操作:
void sig\u处理程序(int sig,siginfo\u t*info,void*ignore){
// ...
杀死(信息->;si_pid,SIGUSR1);
}
内部主(空){
struct sigaction act={.sa_sigaction=sig_handler,.flags=sa_SIGINFO};
sigemptyset(和act.sa_面具);
sigaction(SIGUSR1和act,0);
sigaction(SIGUSR2和act,0);
// ...
}
如果您想执行此操作,那么我将客户端修改留给您,但我建议您考虑这一方(至少)通过“代码”> SIGWAITE()/代码>同步地接收信号,而不是通过信号处理程序异步接收。