Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 我通过一个命名管道传输了一个std::pair,它是如何工作的?_Sockets_C++11_Stl_Pipe_Ipc - Fatal编程技术网

Sockets 我通过一个命名管道传输了一个std::pair,它是如何工作的?

Sockets 我通过一个命名管道传输了一个std::pair,它是如何工作的?,sockets,c++11,stl,pipe,ipc,Sockets,C++11,Stl,Pipe,Ipc,我在Linux中使用读写函数在命名管道上传递了一个std::pair。我通过引用来传递它,并通过引用来阅读它。那是怎么回事?据我所知,std::pair没有序列化,当引用超出范围时会发生什么。是否可以移动对象或通过引用复制 我很困惑 我是C++新手,所以我的指针和参考知识有点差,但是从我知道的,我把地址传递到管道上,然后把读的边对象指向这个新地址。 虽然读取端对象是一个对象,而不是指针。那么,它的旧/原始实例会发生什么变化 我使用以下代码编写: std::pair<int, somestr

我在Linux中使用读写函数在命名管道上传递了一个std::pair。我通过引用来传递它,并通过引用来阅读它。那是怎么回事?据我所知,std::pair没有序列化,当引用超出范围时会发生什么。是否可以移动对象或通过引用复制

我很困惑

我是C++新手,所以我的指针和参考知识有点差,但是从我知道的,我把地址传递到管道上,然后把读的边对象指向这个新地址。 虽然读取端对象是一个对象,而不是指针。那么,它的旧/原始实例会发生什么变化

我使用以下代码编写:

std::pair<int, somestruct> sample_pair;
write(FD, &sample_pair, sizeof(sample_pair));
std::pair<int, somestruct> sample_pair;
read(FD, &sample_pair, sizeof(sample_pair));
并使用以下代码阅读:

std::pair<int, somestruct> sample_pair;
write(FD, &sample_pair, sizeof(sample_pair));
std::pair<int, somestruct> sample_pair;
read(FD, &sample_pair, sizeof(sample_pair));
您根本没有通过管道发送std::pair的地址。而是发送std::pair的实际内容

将std::pair实例的地址作为要写入的起始地址,告诉它读取从该初始地址开始的sizeofsample\u对字节数,并将它们顺序写入管道。因此,存储在std::pair中的原始字节将按管道上的原样写入

您正在将std::pair实例的地址作为要读取的起始地址,告诉它从管道中读取sizeofsample\u对字节数,并按顺序将它们保存到该初始地址。因此,从管道接收的原始字节存储在std::pair内部

也就是说,以这种方式发送std::pair仍然是未定义的行为,因为std::pair的实际内存布局是特定于实现的,特别是在两个字段之间可能存在的任何对齐填充方面。您需要手动将数据序列化为可以安全跨越流程边界的格式,然后在另一端对其进行反序列化

例如,假设somestruct是自包含的,没有指向外部数据的指针,并且没有自身的对齐问题,则可以简单地分别发送两个字段,例如:

#pragma pack(push, 1)
struct somestruct
{
    int8_t value1;
    int16_t value2;
    int32_t value3;
    char data[256];
};
#pragma pack(pop)
或者,您可以单独发送值:

void sendInt8(int FD, int8_t value)
{
    write(FD, &value, sizeof(value));
}

void sendInt16(int FD, int16_t value)
{
    value = htons(value);
    write(FD, &value, sizeof(value));
}

void sendInt32(int FD, int32_t value)
{
    value = htonl(value);
    write(FD, &value, sizeof(value));
}

void sendStr(int FD, const std::string &value)
{
    sendInt32(FD, value.length());
    write(FD, value.c_str(), value.length());
}

...

std::pair<int32_t, somestruct> sample_pair;
// populate as needed...

sendInt32(FD, sample_pair.first);
sendInt8(FD, sample_pair.second.value1);
sendInt16(FD, sample_pair.second.value2);
sendInt32(FD, sample_pair.second.value3);
sendStr(FD, sample_pair.second.data);
std::pair<int32_t, somestruct> sample_pair;
// populate as needed...

std::vector<uint8_t> buffer(
  sizeof(int32_t) +
  sizeof(int8_t) +
  sizeof(int16_t) +
  sizeof(int32_t) +
  sizeof(int32_t) +
  sample_pair.second.data.length()
);

uint8_t *ptr = &buffer[0];

*reinterpret_cast<int32_t*>(ptr) = htonl(sample_pair.first);
ptr += sizeof(int32_t);

*reinterpret_cast<int8_t*>(ptr) = sample_pair.second.value1;
ptr += sizeof(int8_t);

*reinterpret_cast<int16_t*>(ptr) = htons(sample_pair.second.value2);
ptr += sizeof(int16_t);

*reinterpret_cast<int32_t*>(ptr) = htonl(sample_pair.second.value3);
ptr += sizeof(int32_t);

*reinterpret_cast<int32_t*>(ptr) = htonl(sample_pair.second.data.length());
ptr += sizeof(int32_t);

std::copy(sample_pair.second.data.cbegin(), sample_pair.second.data.cend(), reinterpret_cast<char*>(ptr));

int32_t len = htonl(buffer.size());
write(FD, &len, sizeof(len));
write(FD, buffer.data(), buffer.size());
std::pair<int32_t, somestruct> sample_pair;

int32_t len;
read(FD, &len, sizeof(len));
len = ntohl(len);

std::vector<uint8_t> buffer(len);
uint8_t *ptr = &buffer[0];

read(FD, ptr, len);

sample_pair.first = ntohl(*reinterpret_cast<int32_t*>(ptr));
ptr += sizeof(int32_t);

sample_pair.second.value1 = *reinterpret_cast<int8_t*>(ptr);
ptr += sizeof(int8_t);

sample_pair.second.value2 = ntohs(*reinterpret_cast<int16_t*>(ptr));
ptr += sizeof(int16_t);

sample_pair.second.value3 = ntohl(*reinterpret_cast<int32_t*>(ptr));
ptr += sizeof(int32_t);

len = ntohl(*reinterpret_cast<int32_t*>(ptr));
ptr += sizeof(int32_t);

sample_pair.second.data.assign(reinterpret_cast<char*>(ptr), len);
void sendInt8(int FD, int8_t value)
{
    write(FD, &value, sizeof(value));
}

void sendInt16(int FD, int16_t value)
{
    value = htons(value);
    write(FD, &value, sizeof(value));
}

void sendInt32(int FD, int32_t value)
{
    value = htonl(value);
    write(FD, &value, sizeof(value));
}

void sendStr(int FD, const std::string &value)
{
    sendInt32(FD, value.length());
    write(FD, value.c_str(), value.length());
}

...

std::pair<int32_t, somestruct> sample_pair;
// populate as needed...

sendInt32(FD, sample_pair.first);
sendInt8(FD, sample_pair.second.value1);
sendInt16(FD, sample_pair.second.value2);
sendInt32(FD, sample_pair.second.value3);
sendStr(FD, sample_pair.second.data);
int8_t readInt8(int FD)
{
    int8_t value;
    read(FD, &value, sizeof(value));
    return value;
}

int16_t readInt16(int FD)
{
    int16_t value;
    read(FD, &value, sizeof(value));
    return ntohs(value);
}

int32_t readInt16(int FD)
{
    int32_t value;
    read(FD, &value, sizeof(value));
    return ntohl(value);
}

std::string readStr(int FD)
{
    std::string value;
    int32_t len = readInt32(FD);
    if (len > 0)
    {
        value.resize(len);
        read(FD, &value[0], len);
    }
    return value;
}

...

std::pair<int32_t, somestruct> sample_pair;

sample_pair.first = readInt32(FD);
sample_pair.second.value1 = readInt8(FD);
sample_pair.second.value2 = readInt16(FD);
sample_pair.second.value3 = readInt32(FD);
sample_pair.second.data = readStr(FD);