#c #unix #client-server #ipc #fifo
#c #unix #клиент-сервер #ipc #фифо #fifo
Вопрос:
Я хочу, чтобы сообщение отправлялось и получалось через 2 однонаправленных FIFO
Поток данных
FIFO1 stdin---> родительский (клиентский) writefd---> FIFO1-> дочерний (серверный) readfd FIFO2 дочерний (серверный) writefd2----> FIFO2---> родительский (клиентский) readfd2---> стандартный вывод
Мне нужно иметь сообщение с граничной структурой mesg_len mesg_type mesg_data
Функция заключается в том, что если пользователь вводит «Knock Knock» в stdin, который направляет к клиенту, клиент отправляет это сообщение на сервер через FIFO1, сервер сравнивает строку, если совпадает с «Knock Knock», затем сервер отвечает сообщением «Кто там?» клиенту через FIFO2, и клиент записывает это сообщение в стандартный вывод.
Интерактивная часть похожа:
клиент: Тук-тук сервер: кто там клиент: Эрик сервер: Эрик, добро пожаловать клиент: выход завершение всех сигналов
Ниже приведен мой код:
Мне нужна помощь по сигналам 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 %dn", 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 %dn", 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,amp;mesg);//write to IPC channel
//read from IPC,write to std output
if((n=mesg_recv(readfd,amp;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,amp;mesg))==0){
printf("Message missing");
exit(1);
}
mesg.mesg_data[n]='';
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,amp;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) amp;amp; (errno!=EEXIST)){
printf("can't create %s",FIFO1);
exit(1);
}
if ((mkfifo(FIFO2,FILE_MODE)<0) amp;amp; (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;
}
Комментарии:
1. Если это домашнее задание, вы должны пометить его как таковое. Что еще более важно, многие программисты на языке C обычно не сканируют вопросы, помеченные только как unix, поэтому соответствующий языковой тег поможет # людям, которые рассматривают вашу проблему. Удачи.
Ответ №1:
Вы открываете FIFO2 как WRONLY, а FIFO1 как RDONLY в обоих процессах. Открытие канала для чтения будет блокироваться до тех пор, пока другая сторона не откроется для записи, и вы не откроетесь для чтения с обеих сторон — следовательно, зашли в тупик.
Комментарии:
1. @Juanita — вместо использования
kill
, что очень жестоко, используйте свою систему обмена сообщениями, чтобы отправить клиенту сообщение о выходе.2. Домашнее требование состоит в том, чтобы прекратить все сигналы, выйти из программы, когда клиент вводит «exit». пожалуйста, помогите.