繁体   English   中英

如何在不破坏数据的情况下将缓冲区投射到结构?

[英]How would one cast a buffer to a struct without corrupting the data?

我正在从事我的网络项目,以便更多地了解网络,现在我设计了一个简单的协议/结构,将其填充并发送到服务器,问题是所有矢量以及可能的数组在服务器端。

我会尝试用代码来解释它,这样很容易。

我的协议:

typedef struct NETWORK_PROTOCOL {
    int packet_size;
    int number_of_data_files;
    std::vector<std::string> data_files;
}

所以它是一个非常简单的协议,我所做的是我在客户端填充了数据并对其完全有效,但是,一旦我将其发送到服务器并尝试将其转换回向量,该向量是无效的,但是整数仍然有效。

这就是我从客户端创建和发送数据的方式:

NETWORK_PROTOCOL Protocol;

//Fills protocol with data

int sendt = send(ClientSocket, (const char*)&Protocol, Protocol.packet_size, 0);

当它到达服务器时,我仍然可以获得完整的数据大小,但是正如我之前所说,它不能正确转换回:/

尝试将其投射回服务器端的代码:

NETWORK_PROTOCOL* Protocol;

iResult = recv(ClientSocket, buffer, BUFFLEN, 0);

//then i have some validation code to check if the whole packet arrived since its TCP

Protocol = reinterpret_cast<NETWORK_PROTOCOL*>(buffer);
//And now the vector is invalid :/

我不是很确定如何解决这个问题,我认为将其转换回去很容易,因为双方的数据完全相同。 感谢您提供任何解决此问题的帮助。

std :: vector不能以这种方式传输:内部使用指针,因此您仅发送一个指针,而没有任何实际信息,并且该指针在接收端无效。

为了发送向量的内容,您需要以某种方式对其进行序列化(将其转换为可以轻松传输的表示形式)。 例如,您可以使用Boost.Serialization

#include <sstream>

// include headers that implement a archive in simple text format
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>

struct NETWORK_PROTOCOL
{
private:
    friend class boost::serialization::access;
    // When the class Archive corresponds to an output archive, the
    // & operator is defined similar to <<.  Likewise, when the class Archive
    // is a type of input archive the & operator is defined similar to >>.
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & packet_size;
        ar & number_of_data_files; // you don't actually need it
        ar & data_files;
    }
public:
    int packet_size;
    int number_of_data_files;
    std::vector<std::string> data_files;
};

现在您可以像这样序列化它:

    std::ostringstream ofs;
    boost::archive::text_oarchive oa(ofs);
    oa << protocol; // protocol is your instance of NETWORK_PROTOCOL, which you want to send

   // and then you'll be able to get a buffer from ofs using ofs.str()

像这样反序列化:

    NETWORK_PROTOCOL protocol;
    std::istringstream ifs(buf);
    boost::archive::text_iarchive ia(ifs);
    ia >> protocol;

对于实际用途,您可能需要使用二进制存档。 如果您决定使用boost.serialization,建议您从此处开始。

您可能还喜欢Google协议缓冲区: https : //developers.google.com/protocol-buffers/docs/cpptutorial

此评论的长度超出了允许范围。 所以我把它作为答案。 尽管我认为它可以部分回答。

要一次发送所有数据,这将浪费空间和带宽,因为您必须使用最大数量的名称及其大小。 因此,我建议您分阶段进行传输。

在第一个阶段中,您将发送正在传输的文件名数量。 通过这种方式,您可以准备服务器以接收n文件名。 然后在第二阶段中,将循环分成两个传输。 第一次发送时,您发送文件名的大小,然后准备一个缓冲区来接收文件名。

对于这些模式,您仅使用基本类型( size_tchar * )。

在服务器端,如果您想给出这种错觉,则可以构建vector<string>

希望对您有帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM