使用 2 个 FIFO 的客户端-服务器 IPC 消息中的 Kill() 函数问题
我想要发送消息并发送消息通过2个单向FIFO接收
数据流
FIFO1 stdin--->parent(client) writefd--->FIFO1-->child(server) readfd FIFO2 child(server) writefd2---->FIFO2--->parent(client) readfd2--->stdout
我需要有边界结构消息mesg_len+mesg_type+mesg_data
该功能是,如果用户在stdin上输入“Knock Knock”,该消息定向到客户端,客户端通过FIFO1将此消息发送到服务器,服务器比较该字符串,如果与“Knock Knock”匹配,则服务器回复消息“Who’s there?”通过 FIFO2 发送给客户端,客户端将此消息写入标准输出。
交互部分如下:
client:Knock Knock server:who's there client:eric server:eric,welcome client:exit all signal terminate
下面是我的代码:
当客户端键入“exit”时,我需要有关kill() 信号的帮助。调用kill() 后,客户端进程似乎仍然存在。所以我需要输入 ctrl+c 来结束
请帮助我。多谢!
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#define MAX_BUF 100
#define MAXMESGDATA (MAX_BUF - 2* sizeof(long))
#define MESGHDRSIZE (sizeof(struct mymesg)-MAXMESGDATA)
#define FIFO1 "/tmp/fifo.1"
#define FIFO2 "/tmp/fifo.2"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
struct mymesg{
long mesg_len; //byte in mesg_data
long mesg_type; //message type
char mesg_data[MAXMESGDATA];
};
ssize_t mesg_send (int fd, struct mymesg *mptr){
return (write (fd,mptr,MESGHDRSIZE + mptr->mesg_len));
}
ssize_t mesg_recv(int fd,struct mymesg *mptr){
size_t len;
ssize_t n;
if ((n=read(fd,mptr,MESGHDRSIZE))==0) {//read hear first, get len of data
return 0; //end of file
} else if (n!=MESGHDRSIZE){
printf("message header: expected %d, got %d\n", MESGHDRSIZE,n);
exit(1);
}
if ((len=mptr->mesg_len)>0)
{
if ((n=read(fd,mptr->mesg_data,len))!=len)
{
printf("message data: expected %d, got %d\n", len,n);
exit(1);
}
}
return len;
}
void client(int readfd,int writefd){
size_t len;
ssize_t n;
struct mymesg mesg;
for (;;)
{
printf("\nClient:");
fgets(mesg.mesg_data,MAXMESGDATA,stdin);//read mesg
len=strlen(mesg.mesg_data);
if (mesg.mesg_data[len-1]=='\n') //ignore newline
len--;
mesg.mesg_len=len;
mesg.mesg_type=1;
mesg_send(writefd,&mesg);//write to IPC channel
//read from IPC,write to std output
if((n=mesg_recv(readfd,&mesg))>0)
write(STDOUT_FILENO,mesg.mesg_data,n);
}
}
void server(int readfd,int writefd){
ssize_t n;
struct mymesg mesg;
for(;;)
{
mesg.mesg_type=1;
//read from IPC channel
if ((n=mesg_recv(readfd,&mesg))==0){
printf("Message missing");
exit(1);
}
mesg.mesg_data[n]='\0';
mesg.mesg_len=strlen(mesg.mesg_data);
char* str=NULL;
if (strcasecmp ("Knock Knock", mesg.mesg_data)==0){
str="Server:Who's there?";
strcpy(mesg.mesg_data,str);
mesg.mesg_len=strlen(str)-1;
}
else if(strcasecmp ("Eric", mesg.mesg_data)==0){
str="Server:Eric,Welcome!";
strcpy(mesg.mesg_data,str);
mesg.mesg_len=strlen(str)-1;
}
else if(strcasecmp ("Exit", mesg.mesg_data)==0){
kill(getpid(),SIGTERM);
kill(getppid(),SIGTERM);
exit(0);
}
mesg_send(writefd,&mesg);
}
}
int main(int argc, char ** argv){
/*MAXMESGDATA== 92 bytes; sizeof(struct mymesg)== 100 bytes
2* sizeof(long)== 8 bytes; MESGHDRSIZE ==8 bytes*/
int readfd,writefd;
pid_t childpid;
//create 2 FIFOs
if ((mkfifo(FIFO1,FILE_MODE)<0) && (errno!=EEXIST)){
printf("can't create %s",FIFO1);
exit(1);
}
if ((mkfifo(FIFO2,FILE_MODE)<0) && (errno!=EEXIST)){
printf("can't create %s",FIFO1);
unlink(FIFO1);
exit(1);
}
if ((childpid=fork()==0)){//child
readfd=open(FIFO1,O_RDONLY,0);
writefd=open(FIFO2,O_WRONLY,0);
server(readfd,writefd);
exit(0);
}
//parent
writefd=open(FIFO1,O_WRONLY,0);
readfd=open(FIFO2,O_RDONLY,0);
client(readfd,writefd);
waitpid(childpid,NULL,0);
close(readfd);
close(writefd);
unlink(FIFO1);
unlink(FIFO2);
return EXIT_SUCCESS;
}
I want to have a message send & receive through 2 uni-direction FIFO
Flow of data
FIFO1 stdin--->parent(client) writefd--->FIFO1-->child(server) readfd FIFO2 child(server) writefd2---->FIFO2--->parent(client) readfd2--->stdout
I need to have boundary structed message mesg_len+mesg_type+mesg_data
The function is that if user input "Knock Knock" on stdin, which directs to client, client send this message to server through FIFO1, server compares the string, if matches with "Knock Knock", then server reply message "Who's there?" to client through FIFO2, and client write this message to the stdout.
The interactive part is like:
client:Knock Knock server:who's there client:eric server:eric,welcome client:exit all signal terminate
Below is my code:
I need help on kill() signals when client types "exit".It seems the client process still live after call kill(). So i need to type ctrl+c to end
Please help me. Thanks a lot!
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#define MAX_BUF 100
#define MAXMESGDATA (MAX_BUF - 2* sizeof(long))
#define MESGHDRSIZE (sizeof(struct mymesg)-MAXMESGDATA)
#define FIFO1 "/tmp/fifo.1"
#define FIFO2 "/tmp/fifo.2"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
struct mymesg{
long mesg_len; //byte in mesg_data
long mesg_type; //message type
char mesg_data[MAXMESGDATA];
};
ssize_t mesg_send (int fd, struct mymesg *mptr){
return (write (fd,mptr,MESGHDRSIZE + mptr->mesg_len));
}
ssize_t mesg_recv(int fd,struct mymesg *mptr){
size_t len;
ssize_t n;
if ((n=read(fd,mptr,MESGHDRSIZE))==0) {//read hear first, get len of data
return 0; //end of file
} else if (n!=MESGHDRSIZE){
printf("message header: expected %d, got %d\n", MESGHDRSIZE,n);
exit(1);
}
if ((len=mptr->mesg_len)>0)
{
if ((n=read(fd,mptr->mesg_data,len))!=len)
{
printf("message data: expected %d, got %d\n", len,n);
exit(1);
}
}
return len;
}
void client(int readfd,int writefd){
size_t len;
ssize_t n;
struct mymesg mesg;
for (;;)
{
printf("\nClient:");
fgets(mesg.mesg_data,MAXMESGDATA,stdin);//read mesg
len=strlen(mesg.mesg_data);
if (mesg.mesg_data[len-1]=='\n') //ignore newline
len--;
mesg.mesg_len=len;
mesg.mesg_type=1;
mesg_send(writefd,&mesg);//write to IPC channel
//read from IPC,write to std output
if((n=mesg_recv(readfd,&mesg))>0)
write(STDOUT_FILENO,mesg.mesg_data,n);
}
}
void server(int readfd,int writefd){
ssize_t n;
struct mymesg mesg;
for(;;)
{
mesg.mesg_type=1;
//read from IPC channel
if ((n=mesg_recv(readfd,&mesg))==0){
printf("Message missing");
exit(1);
}
mesg.mesg_data[n]='\0';
mesg.mesg_len=strlen(mesg.mesg_data);
char* str=NULL;
if (strcasecmp ("Knock Knock", mesg.mesg_data)==0){
str="Server:Who's there?";
strcpy(mesg.mesg_data,str);
mesg.mesg_len=strlen(str)-1;
}
else if(strcasecmp ("Eric", mesg.mesg_data)==0){
str="Server:Eric,Welcome!";
strcpy(mesg.mesg_data,str);
mesg.mesg_len=strlen(str)-1;
}
else if(strcasecmp ("Exit", mesg.mesg_data)==0){
kill(getpid(),SIGTERM);
kill(getppid(),SIGTERM);
exit(0);
}
mesg_send(writefd,&mesg);
}
}
int main(int argc, char ** argv){
/*MAXMESGDATA== 92 bytes; sizeof(struct mymesg)== 100 bytes
2* sizeof(long)== 8 bytes; MESGHDRSIZE ==8 bytes*/
int readfd,writefd;
pid_t childpid;
//create 2 FIFOs
if ((mkfifo(FIFO1,FILE_MODE)<0) && (errno!=EEXIST)){
printf("can't create %s",FIFO1);
exit(1);
}
if ((mkfifo(FIFO2,FILE_MODE)<0) && (errno!=EEXIST)){
printf("can't create %s",FIFO1);
unlink(FIFO1);
exit(1);
}
if ((childpid=fork()==0)){//child
readfd=open(FIFO1,O_RDONLY,0);
writefd=open(FIFO2,O_WRONLY,0);
server(readfd,writefd);
exit(0);
}
//parent
writefd=open(FIFO1,O_WRONLY,0);
readfd=open(FIFO2,O_RDONLY,0);
client(readfd,writefd);
waitpid(childpid,NULL,0);
close(readfd);
close(writefd);
unlink(FIFO1);
unlink(FIFO2);
return EXIT_SUCCESS;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在这两个进程中,您将 FIFO2 作为 WRONLY 打开,将 FIFO1 作为 RDONLY 打开。打开管道进行读取将会阻塞,直到另一端打开进行写入,并且您在两侧都打开进行读取 - 因此陷入僵局。
You open FIFO2 as WRONLY and FIFO1 as RDONLY in both the processes. Opening pipe for read will block until the other side opens for write, and you open for read on both sides - hence deadlocked.