簡體   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