#c #unix #ipc #pipe #message-queue
#c #unix #ipc #канал #очередь сообщений
Вопрос:
Я хочу, чтобы сообщение отправлялось и получалось по двум полудуплексным каналам
Поток данных stdin верхней половины канала—>родительский (клиентский) fd1[1]—> pipe1-> дочерний (серверный) fd1[0] дочерний (серверный) fd2 нижней половины канала[1]—-> pipe2—> родительский (клиентский) fd2[0]—> стандартный вывод
Мне нужно иметь сообщение с граничной структурой mesg_len mesg_type mesg_data
Функция заключается в том, что если пользователь вводит «Knock Knock» в stdin, который направляет клиенту, клиент отправляет это сообщение серверу по верхней половине канала, сервер сравнивает строку, если совпадает с «Knock Knock», затем сервер отвечает сообщением «Кто там?» клиенту через нижнюю половину канала, и клиент записывает это сообщение в стандартный вывод.
Ниже приведен мой код: у меня проблема:
- при запуске сервера сообщение пустое, когда я что-либо набираю на консоли, я получаю mesg_headersize и mesg_datasize оба -1. Программа не может продолжить. Как решить эту проблему?
Пожалуйста, помогите. Большое спасибо.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#define MAX_BUF 100
#define MAXMESGDATA (MAX_BUF - 2* sizeof(long))
#define MESGHDRSIZE (sizeof(struct mymesg)-MAXMESGDATA)
struct mymesg{
long mesg_len; //byte in mesg_data
long mesg_type; //message type
char mesg_data[MAXMESGDATA];
};
ssize_t mesg_send(int,struct mymesg *);
ssize_t mesg_recv(int,struct mymesg *);
void client (int,int),server(int,int);
int main(int argc, char ** argv){
//MAXMESGDATA== 92 bytes
//sizeof(struct mymesg)== 100 bytes
//2* sizeof(long)== 8 bytes
//MESGHDRSIZE ==8 bytes
int pipe1[2],pipe2[2];
pid_t childpid;
pipe(pipe1); //create 2 pipes
pipe(pipe2);
if ((childpid=fork())==0) { //child
close(pipe1[1]);
close(pipe2[0]);
server(pipe1[0],pipe2[1]);
exit(0);
}
//parent
close(pipe1[0]);
close(pipe2[1]);
client(pipe1[1],pipe2[0]);
waitpid (childpid,NULL,0);
return EXIT_SUCCESS;
}
void client(int readfd,int writefd){
size_t len;
ssize_t n;
struct mymesg mesg;
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
while((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;
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);
//printf("%sn",mesg.mesg_data);
if (strcasecmp ("Knock Knock", mesg.mesg_data)==0){
char* str="Who's there?";
strcpy(mesg.mesg_data,str);
mesg.mesg_len=strlen(str)-1;
}
mesg_send(writefd,amp;mesg);
}
Ответ №1:
Ваша первая проблема заключается в том, что вы поменяли местами аргументы вашей клиентской функции. Дескриптором чтения всегда является дескриптор 0. Итак, ваш код должен гласить:
client(pipe2[0],pipe1[1]);
Но у вас есть проблемы, которые намного глубже этого. Вы собираетесь неправильно использовать этот заголовок / данные. Не записывайте структуры как механизм IPC. Это вызовет у вас многочисленные трудности, особенно если вы переходите от использования каналов к использованию сокетов TCP.
Например, в моей системе размер заголовка составляет 16 байт, а не 8. И sizeof mymesg
равно 104, а не 100. Это потому, что я работаю в 64-разрядной системе, и в моей системе длины составляют 8 байт, и это также увеличивает размер структур, кратный 8 байтам.
Вероятно, я смогу вам помочь со второй частью этого. Но мне нужно будет узнать больше о том, о чем вы думали и для чего вы это используете.