我很擅长用c ++编写,我正在使用管道在进程之间进行通信。我编写了一个非常简单的程序,当我发送字符串或整数时,但当我尝试发送一个结构(在这种情况下是消息)时,当我尝试在另一侧读取它时,我得到null。有没有人对他们分享的内容有所了解?谢谢你的时间。
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define BUFFER_LEN sizeof(message)
using namespace std;
struct message{
int from;
string msg;
};
void childCode(int *pipeOUT, int *pipeIN, message buffer){
// Local Buffer for input from pipeIN
cout << "Child: Sending Message"<< endl;
buffer.msg = "Child:I am the child!!";
write(pipeOUT[1],(char*) &buffer, BUFFER_LEN); // Test Child -> Parent comms
cout << "Child: Message Sent"<<endl;
read(pipeIN[0],(char*) &buffer,BUFFER_LEN); // Test Child <- Parent comms
cout << "Child: Recieved: "<< buffer.msg << endl;
cout << "Child Exiting..."<< endl;
exit(0); // Child process End
}
int main(int argCount, char** argVector){
pid_t pid;
int childPipeIN[2];
int childPipeOUT[2];
message buffer; // Buffer for reading from pipe
// Make Parent <- Child pipe
int ret = pipe(childPipeIN);
if (ret == -1){
perror("There was an error creating the childPipeIN. Exiting...");
exit(1);
}
// Make Parent -> Child pipe
ret = pipe(childPipeOUT);
if (ret == -1){
perror("There was an error creating the childPipeOUT. Exiting...");
exit(1);
}
// Fork off Child
pid = fork();
if (pid == -1){
perror("There has been an issue forking off the child. Exiting...");
exit(1);
}
if (pid == 0){ // Child code
cout << "Child PID = " << getpid() << endl;
childCode(childPipeIN,childPipeOUT,buffer);
}
else{ // Parent Code
cout << "Parent PID = " << getpid() << endl;
// Test Parent <- Child comms
read(childPipeIN[0], (char*) &buffer, BUFFER_LEN);
cout << "Parent: I recieved this from the child...\n" << buffer.msg << endl;
buffer.msg = "Parent: Got you message!";
// Test Parent -> Child comms
write(childPipeOUT[1], (char*) &buffer, BUFFER_LEN);
wait(null);
cout << "Parent: Children are done. Exiting..." << endl;
}
exit(0);
}
答案 0 :(得分:3)
呀。我投票结束了。然后我更仔细地阅读Dupe并意识到它没有很好地解释问题或解决方案,并且解决方案并不真正符合OP的意图。
不只是将std::string
写入管道。 std::string
不是一小块数据。那里有指针不睡觉。
想到这一点,将std::string
写入任何东西都是非常危险的。包括另一个std::string
。我不会,也不能用文件。这种smurf难以押韵,所以我将不再与Seuss博士合作。
对于另一个进程,引用包含string
数据的存储的指针,允许string
s可调整大小的魔力,可能意味着什么都没有,如果它确实意味着什么,你可以打赌,这不是你想搞砸的东西,因为它肯定不是string
的数据。
即使在另一个std::string
的同一个进程中,两个字符串也不能和平共存,指向同一个内存。当一个人超出范围,调整大小或做其他任何会改变string
不良的事情时,都会发生。
不相信我?检查BUFFER_LEN
。无论您的邮件有多大,BUFFER_LEN
都不会发生变化。
这适用于您想要编写的不是简单数据块的所有内容。整数,写下来。整数结构和固定大小的字符数组,写出来。 std::vector
?没有这样的运气。你可以写std::vector::data
当且仅当它包含的内容是微不足道的时候。
std::is_pod
may help you decide what you can and cannot read and write the easy way.
Serialize the data.建立定义数据格式的通信协议,然后使用该协议作为读写代码的基础。
移动string
的典型解决方案是空终止缓冲区,就像在C的好日子里一样,并将string
的大小预先设置为string
中的字符帕斯卡的美好时光。
我喜欢Pascal方法,因为它允许您提前调整接收器缓冲区的大小。使用null终止时,你必须播放几十个Getta字节,寻找null终止符,并希望你的缓冲区足够大,或者通过缓冲区调整大小的动态分配和复制来加重丑陋。
写作几乎就是你现在所做的,但结构成员的结构成员。在上面的例子中
message.from
写入管道。message.msg
的长度写入管道。message.msg.data()
写入管道。两个警告:
int
可能与另一个人long
的大小相同,因此请fixed width integers使用message.from
。 阅读有点复杂,因为单次调用将返回最多所请求的长度。获取所需的所有数据可能需要多次读取,因此您需要一个循环的函数,直到所有数据到达或无法到达,因为管道,文件,套接字等都已关闭。
message.msg
全部到达。message.msg.resize(length)
的所有长度都到达。message.msg
调整message.msg
的大小来保留邮件。message.msg.data()
都到达。您可以直接将消息阅读{{1}}。