如何通过管道C 发送结构
How to send a struct over a pipe C++
我是在C 上写作的新手,并且正在努力使用管道在过程之间进行交流。我编写了一个非常简单的程序,该程序在发送字符串或整数时可以工作,但是当我尝试发送struct(在这种情况下是消息)时,我会在另一侧阅读它时会变得无效。有人对此有所了解吗?感谢您的时间。
#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);
}
是的。我投票关闭。然后,我更仔细地阅读了杜佩(Dupe),并意识到它不能很好地解释问题或解决方案,而解决方案并不符合OP的意图。
问题:
一个人不简单地将std::string
写入管道。std::string
不是一个琐碎的数据。那里有没有睡觉的指针。
想到这一点,将std::string
写入任何东西都是血腥的。包括另一个std::string
。我不会,无法使用文件。这个蓝精灵很难押韵,所以我不会再和苏斯博士一起去。
转到另一个过程,引用包含string
数据的存储的指针,允许string
s可以解析的魔术,可能绝对没有任何意义,如果确实意味着什么搞砸了,因为这当然不是string
的数据。
即使在另一个std::string
中的同一过程中,两个字符串也无法和平共存指向相同的记忆。当一个人脱离范围,调整大小或实际上会发生任何其他任何突变string
不良的东西。
不相信我?检查BUFFER_LEN
。无论您的消息有多大,BUFFER_LEN
都不会改变。
这适用于您想编写的所有内容,这不是简单的数据。整数,书写。整数的结构和固定大小的字符数组,写下。std::vector
?没有这样的运气。您可以在且只有当它包含的任何内容都是微不足道的情况下编写std::vector::data
。
std::is_pod
可以帮助您确定可以和读写简单的方法。
解决方案:
序列化数据。建立一个定义数据格式的通信协议,然后将该协议用作阅读和编写代码的基础。
移动string
的典型解决方案就像在C的好时代一样终止缓冲区,并将string
的大小预留到string
中的字符,就像Pascal的好时代一样。
我喜欢Pascal方法,因为它允许您提前尺寸接收器的缓冲区。通过NULL终止,您必须播放几十轮Getta-byte,以寻找无效的终结器,并希望您的缓冲区足够大,或者通过缓冲区的动态分配和复制缓冲区的调整。
写作几乎是您现在正在做的事情,但是结构成员结构成员。在上述情况下
- 将
message.from
写入管道。 - 将
message.msg
的长度写入管道。 - 将
message.msg.data()
写入管道。
两个警告:
- 观看你的末日!牢固建立您的协议使用的字节顺序。如果本地Endian不匹配协议Endian,则可能需要进行一些换位才能重新定义消息。
- 一个人的
int
可能是另一个人的long
的大小,因此请使用固定宽度整数。
读取更为复杂,因为单个读取的呼叫将返回最多请求的长度。获取所需的所有数据可能需要多个读取,因此您需要一个循环的函数,直到所有数据到达或无法到达,因为管道,文件,套接字和关闭的内容。
- 阅读循环直到所有
message.from
到达。 - 读取循环,直到
message.msg
的所有长度到达为止。 - 使用
message.msg.resize(length)
到大小message.msg
保存消息。 - 阅读循环,直到所有
message.msg
都到达。您可以将消息直接读取到message.msg.data()
。
- 通过方法访问结构
- 如何传递带有通过引用传递的结构参数的函数?
- 通过 NIF 从C++返回自定义数据结构
- 通过指针偏移量访问结构变量值
- 如何通过UDP接收QByteArray并将其解析为位字段结构?
- C++ 通过函数传递自定义结构
- 如何通过向量中的结构 id 获取索引号
- 使用智能指针指向 C 库中的结构,该结构通过 typedef 隐藏实现(即不完整的类型)
- 通过引用传递结构数组
- 如何通过 C 在用户定义的结构中编写双数组并使用 CTYPE 传递给 Python
- 如何通过不同的指针使用类的对象访问结构?(链表)(C++)
- 在VS 2017中,朋友通过具有私有析构函数的结构的unique_ptr向量进行迭代失败
- 您自己的类型的结构化绑定,不是结构或元组(通过公共成员函数)
- 如何在C++中通过引用传递结构?
- 通过指针算法访问结构数据成员
- C 通过 UART 将结构发送到 Python
- 通过指针算法调用结构的结构属性
- 在通过 P/Invoke 获取的 C++ 结构上设置 C# 回调
- 如何将存储在列表中的结构成员通过参考将其传递给函数
- c++是一种基于组件的体系结构,通过继承实现,被认为是良好的实践