0
votes

I want to have a message send & receive through 2 half-duplex pipes

Flow of data top half pipe stdin--->parent(client) fd1[1]--->pipe1-->child(server) fd1[0] bottom half pipe child(server) fd2[1]---->pipe2--->parent(client) fd2[0]--->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 on the top half pipe, server compares the string, if matches with "Knock Knock", then server reply message "Who's there?" to client throught the bottom half pipe, and client write this message to the stdout.

Below is my code: I have a problem:

  1. when the server starts, the message is empty, when i type anything on the console, I got mesg_headersize and mesg_datasize both -1. Program can't continue. How to solve this problem?

Please help. Many thanks.

#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,&mesg);//write to IPC channel
    //read from IPC,write to std output
    while((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;
    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);
    //printf("%s\n",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,&mesg);
}
1

1 Answers

0
votes

Your first problem is because you reversed the arguments to your client function. The read descriptor is always descriptor 0. So your code should read:

client(pipe2[0],pipe1[1]);

But you have issues that are far deeper than that. You are going about doing this header/data thing in the wrong way. Do not write structures as an IPC mechanism. This will cause you numerous difficulties, especially if you transition from using pipes to using TCP sockets.

As an example, on my system, the header size is 16 bytes, not 8. And sizeof mymesg is 104, not 100. This is because I'm running on a 64 bit system, and on my system longs are 8 bytes, and it also pads structures to a multiple of 8 bytes in size.

I can probably help you further with the second part of this. But I will need to know more about what you were thinking and what you're using this for.