我想通过 2 个单向 FIFO 发送和接收消息
数据流
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;
}
最佳答案
在这两个进程中,您以 WRONLY 方式打开 FIFO2,以 RDONLY 方式打开 FIFO1。打开管道进行读取将阻塞,直到另一侧打开进行写入,并且您在两侧都打开进行读取 - 因此陷入僵局。
关于c - 使用 2 个 FIFO 的客户端-服务器 ipc 消息中的 kill() 函数问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6290530/