client-server ipc message 2管道通信简单的例子

时间:2011-06-09 01:31:15

标签: c unix ipc pipe message-queue

我想发送一条消息&通过2个半双工管接收

数据流     上半管     stdin ---> parent(客户端)fd1 [1] ---> pipe1 - > child(服务器)fd1 [0]     下半管     child(服务器)fd2 [1] ----> pipe2 ---> parent(客户端)fd2 [0] ---> stdout

我需要有边界构造的消息mesg_len + mesg_type + mesg_data

该功能是如果用户在stdin上输入“Knock Knock”,它指向客户端,客户端将此消息发送到上半部分管道上的服务器,服务器比较字符串,如果匹配“Knock Knock”,则服务器回复消息“谁在那里?”客户端通过下半部分管道,客户端将此消息写入stdout。

以下是我的代码: 我有一个问题:

  1. 当服务器启动时,消息为空,当我在控制台上输入任何内容时,我得到mesg_headersize和mesg_datasize都为-1。程序无法继续。如何解决这个问题?
  2. 请帮忙。非常感谢。

    #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 个答案:

答案 0 :(得分:0)

您的第一个问题是因为您将参数反转为客户端函数。读取描述符始终是描述符0.因此您的代码应为:

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

但是你有比这更深刻的问题。你正在以错误的方式做这个标题/数据事情。不要将结构写为IPC机制。这会给您带来很多困难,特别是如果您从使用管道转换到使用TCP套接字。

例如,在我的系统上,标头大小是16个字节,而不是8.而sizeof mymesg是104,而不是100.这是因为我在64位系统上运行,在我的系统上运行long是8个字节,它还将结构填充为8个字节的倍数。

我可以帮助你进一步完善第二部分。但我需要了解更多关于你在想什么以及你正在使用它的内容。