c++ - 如何在C++中使用管道构建聊天程序

标签 c++ pipe ipc

我想实现一个运行小程序1或小程序2的小程序,具体取决于调用main时输入的参数。打开2个终端和第1个聊天室后,我希望在2个终端之间发送小字符串消息。
我尝试实现一个简单的管道程序,在该程序中,进程将以读取或写入的方式打开管道。然后,如果进程不是您用于其他目的的管道,则该进程将关闭相应的一端,读取端或写入端。打开2个终端,并使用参数0或1调用main时,我调用2个进程来打开管道。
但是,我在运行程序以在2个进程之间连续发送消息时遇到麻烦。每当检测到键盘输入时,该过程就会退出。
我怀疑我没有正确打开管道。 (我的代码中没有打开函数)。打开函数还要求我输入管道的路径名,该路径名位于/ proc / [PID] / fd中。我看到每次运行程序时PID都会不同。因此,如何将其放入开放函数的参数中。
请帮助我修改我的代码。

#include <unistd.h>   /* to use pipe, getpid*/
#include <stdio.h>    /*to use prinf*/
#include <iostream>   /*to use cin, cout*/
#include <string.h>   /*to use str function*/
#include <errno.h>    /* to use with errno*/

int onServiceStart(int chatter, int readPipe[], int writePipe[]){
    if( close(readPipe[1]) == -1 ){   //if use the pipe to read, then close the write end of the pipe
        std::cout<<"Error closing the write end of read pipe"<<errno<<std::endl;
    };
    if( close(writePipe[0]) == -1 ){   //if use the pipe to write, then close the read end of the pipe
        std::cout<<"Error closing the read end of write pipe"<<errno<<std::endl;
    };
    while(true){
        //preparing to get the string from keyboard
        std::string chatInput;
        getline(std::cin, chatInput);
        //send the string to pipe
        if ( write( writePipe[1],chatInput.c_str(),strlen( chatInput.c_str() )) == -1) {
            std::cout<<"Error writing to write end of write pipe"<<errno<<std::endl;
        };
        //preparing the buffer to put the string to after reading from pipe
        char buffer;
        if ( read(readPipe[0],&buffer,1)== -1) {
            std::cout<<"Error reading from read end of read pipe"<<errno<<std::endl;
        };
        std::cout<<buffer;
    }
};

int main(int argc, char *argv[]){
    int chatter = *(argv[1]) - '0';
    int fileDescription1[2], fileDescription2[2] ;
    if ( pipe(fileDescription1)==-1 ) {
        printf("cannot create pipe 1");
    };
    if ( pipe(fileDescription2)==-1 ) {
        printf("cannot create pipe 2");
    };

    switch (chatter) {
        case 0:
            printf("PID %d, chatter 1: \n", getpid());
            onServiceStart(chatter,
                            fileDescription1,       //chatter1 will use fileDescription1 to read,
                            fileDescription2);     //chatter1 will use fileDescription2 to write,

        case 1:
            printf("PID %d, chatter 2: \n", getpid());
            onServiceStart(chatter,
                            fileDescription2,       //chatter2 will use fileDescription2 to read,
                            fileDescription1);    //chatter2 will use fileDescription1 to write,
    }
}

最佳答案

有几个问题。进程立即退出的原因是因为您的程序仅在管道的一侧运行,而不在另一侧运行。例如,如果您使用chatter = 0运行它,则将fileDescription2用作writePipe,但是在onServiceStart()中要做的第一件事是对close()的阅读侧进行writePipe。这意味着每当您写入writePipe[1]时,由于writePipe[0]已关闭,您将收到EPIPE错误。
如果打算启动程序的两个实例,一个实例使用0作为参数,另一个实例使用1,则您需要使用一对named pipes在它们之间进行通信,尽管如果您想双向通信一个命名的UNIX socket更好,因为您只需要一个。
请注意,只有在程序派生或创建多个线程时,使用pipe()创建的一对匿名管道才有用。
另一个问题是您没有从管道的另一端读取整个响应:

//preparing the buffer to put the string to after reading from pipe
char buffer;
if ( read(readPipe[0],&buffer,1)== -1) {
    ...
这仅读取一个字符。之后,您将再次从标准输入中读取内容,因此您发送的每一行只会收到一个字符,这显然不是您想要的。
解决此问题的正确方法是通过传递O_NONBLOCK标志使管道成为非阻塞状态,并使用 select() poll() 循环同时等待来自标准输入和管道的数据。

关于c++ - 如何在C++中使用管道构建聊天程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64290836/

相关文章:

c++ - 为什么函数模板不能部分特化?

c++ - 从 float 转换为 int

node.js - Node JS 请求 + Express Pipe

C 程序对三个命令执行管道

linux - tcpdump 通过 grep 管道写入文件。 (奇怪的数字16)

unix - Unix FIFO/命名管道的命名约定是什么?

linux - 为什么没有创建消息队列

c++ - 更改 QLineEdit 的 x 和 y 位置

c++ - 两个物体的蛮力碰撞检测速度太慢

python-3.x - 多处理 Pipe() 包装器损坏 : Something is Hanging. V5