使用带有字符串数组的管道

Using Pipes with a string array

本文关键字:数组 管道 字符串      更新时间:2023-10-16

尝试创建一个可以插入随机数的管道。分裂成父母和子女,产生随机数,如果孩子,请写信给管道,如果父母阅读。我觉得这很接近,但我的输出是胡说八道。有人可以解释一下管道的作用,并将我指向正确的方向。

    #include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>           /* c++ I/O headers */
#include <string.h>
#include<math.h>
using namespace std;
int main(int argc, char *argv[]) {
//Get the number of random numbers
int numberOfRandomNumbers = stoi(argv[1]);
//char childPipe[200], parentPipe[200]; //pipes to hold numbers
int pid, index, count; //counters
int pipe1[2]; // main pipe
int xyz = pipe(pipe1);  //perform the pipe 
string stringOfRandomNumbers = "";
pid = fork();   //fork the process
//check for errors-------------------------------------------
if(xyz < 0 || pid < 0){
    //break 
    cout << "Error" << endl;
    return 0;
} 
//Check process----------------------------------------------
if (pid == 0) {   /* child */
    srand(pid+4); //seed the random
    int randNum;

    //Start building the string
    stringOfRandomNumbers = "Child, ID = ";
    stringOfRandomNumbers += to_string(pid);
    stringOfRandomNumbers += ", Random numbers: >";

    //Now generate random numbers
    for (index = 0; index < numberOfRandomNumbers; index++) {
        randNum = rand() % 100;
        //add to string.....
        if(index == (numberOfRandomNumbers - 1)){
            //last one
            stringOfRandomNumbers += (to_string(randNum) + "<");
        }
        else{    
             stringOfRandomNumbers = stringOfRandomNumbers + (to_string(randNum) + ", ");  
        }
    }
    cout << endl << stringOfRandomNumbers << "  length = " << stringOfRandomNumbers.length() << endl;
    close(pipe1[0]);    //don't read off of pipe
    write(pipe1[1], stringOfRandomNumbers, stringOfRandomNumbers.length());
    close(pipe1[1]);    //done
}
else {      /* parent */

    // Now generate random numbers
    srand(pid+8);
    int randNum; 
    //Start the string
    stringOfRandomNumbers = "Parent, ID = ";
    stringOfRandomNumbers += to_string(pid);
    stringOfRandomNumbers += ", Random numbers: >";

    //Now generate random numbers
    for (index = 0; index < numberOfRandomNumbers; index++) {
        randNum = rand() % 100;
        //Add to string.....
        if(index == (numberOfRandomNumbers - 1)){
            //last one
            stringOfRandomNumbers += (to_string(randNum) + "<");
        }
        else{    
             stringOfRandomNumbers = stringOfRandomNumbers + (to_string(randNum) + ", ");  
        }
    } 
    close (pipe1[1]);   
    count = read(pipe1[0], stringOfRandomNumbers, stringOfRandomNumbers.length());
    for (index=0; index < count; index++){
            cout << stringOfRandomNumbers[index] << endl;
    }
    close (pipe1[0]);    //done 
}
}

readwrite是旧学校C功能。他们不知道C 字符串是什么,并且假设stringOfRandomNumbers是您要发送的数据或您希望收到的缓冲区的指针。

stringOfRandomNumbers不是指针,您应该收到一条警告消息,即使不是完全拒绝从编译器那里收到的编译。即使是指针,std::string也不一定直接包含其代表的数据。通常,std::string指向动态分配的存储块,如果您write std::string,则编写指针而不是指向的数据。

接收std::string现在有一个指向内存的指针,在发送过程中有意义,但在接收过程中是毫无意义或危险的。如果两者都处于同一过程中,则内存仍然有效,但是您有两个std::string S指向相同的内存。一旦std::string S不符合范围,它将删除内存,并将另一个std::string指向无效的内存。

无论哪种方式,一个都非常糟糕的场景。

接下来,因为您将发送std::string对象,而不是字符串数据,如果字符串数据的长度与sizeof(std::string)完全匹配,则将是愚蠢的运气,因此要发送垃圾数据,也不会发送足够的数据。

您想做的是

的线条
write(pipe1[1], stringOfRandomNumbers.c_str(), stringOfRandomNumbers.length()+1);

std::string::c_str获取一个指向包含字符串数据的缓冲区的指针, 1发送缓冲区的终止null,以便接收器知道字符串停止位置。

这种方法使您遇到问题:我需要阅读多少数据?您必须继续从管道中读取并将读取的内容附加到std::string,直到找到无效。有点奇怪。

但是

uint32_t len = stringOfRandomNumbers.length();
write(pipe1[1], &len, sizeof(len));
write(pipe1[1], stringOfRandomNumbers.c_str(), len);

首先将字符串的长度写为32位无符号整数,然后写入stringOfRandomNumbers Buffer的len字节。

警告:uint32_t是可选的,您的编译器可能不支持。这个想法是要确保两台PC都知道长度的大小,因此您可能必须找到一个固定尺寸,发件人和接收器都同意。

在接收方,

uint32_t len;
read(pipe1[0], &len, sizeof(len)); //read len
std::vector<char> buffer(len+1); // Make buffer big enough for string and terminating null
read(pipe1[0], buffer.data(), len); // read into buffer
buffer[len] = ''; // null terminate
stringOfRandomNumbers = buffer.data();

预计C 17标准可以使其更轻松一些,因为您将能够从std::string请求非const数据指针。提前大小std::string,您可以安全地直接阅读。