boost :: asio :: buffer with vectors structs

时间:2017-10-14 21:39:56

标签: c++ boost-asio

我有两个问题:

  1. 在我的信息结构中,如果我有floatdouble类型而不是std::string,它可以正常工作,但如果我使用std::string,如下所示客户端部分我收到结构但在此之后它只是崩溃。

  2. 我可以t even send it using std :: vector`,就像这样:

  3. struct info
    {
        int id;
        std::string name;
    };
    
    
    int main(int argc, char** argv)
    {
    
        boost::asio::io_service ios;
        boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 12345);
        boost::asio::ip::tcp::socket cl1(ios);
    
        cl1.open(ep.protocol());
        boost::system::error_code ec;
        cl1.connect(ep, ec);
        if (ec == 0)
            cout << "Connected" << endl;
        else {
    
            cout << "Not connected" << endl;
            system("pause");
            return -2;
        }
    
        info student;
        student.id = 7;
        student.name = "Rasul";
    
        cl1.send(boost::asio::buffer(&student, sizeof(student)));
    
        if (ec == 0)
            cout << "Written" << endl;
        else {
    
            cout << "Not written" << endl;
            system("pause");
            return -2;
        }
        cout << "Done" << endl;
        system("pause");
        return 0;
    }
    

1 个答案:

答案 0 :(得分:0)

  
      
  1. 在我的信息结构中,如果我有floatdouble类型而不是std::string它可以正常工作,但如果我使用std::string,如下所示,在我的客户端部分我收到结构但之后就崩溃了。
  2.   

这是因为floatdouble是POD数据类型而std::string不是,违反了合同:

  

boost::asio::buffer函数用于创建缓冲对象来表示原始内存,POD元素数组,POD元素向量或std::string

准确地说,它们意味着“[POD元素的一个(数组|向量)]或[a std::string]”,当你看{{3 }}

添加一个静态断言,你会看到:

static_assert(std::is_pod<info>::value, "whoops, that can't work");
cl1.send(boost::asio::buffer(&student, sizeof(student)));

如果要序列化,则必须编写一些代码。假设架构独立性和可移植性一般不是问题¹,你可以:

int32_t id_and_size[] = {student.id, static_cast<int32_t>(student.name.length())};
assert(id_and_size[1] >= 0); // because `size_t` is unsigned and larger than int32_t

cl1.send(boost::asio::buffer(id_and_size));
cl1.send(boost::asio::buffer(student.name.data(), student.name.length()));

这会将长度与数据分开: Live On Coliru](list of overloads

<00> 00000000:0700 0000 0500 0000 5261 7375 6c ........ Rasul

虽然这容易出错并且乏味。如果您控制两端,请考虑序列化框架(Boost Serialization,Google Protobuf ...)

¹因为您已经提到序列化double等原始二进制形式