简体   繁体   English

C++ 使用 Winsock2 发送 boost::dynamic_bitset 到 function

[英]C++ send boost::dynamic_bitset with Winsock2 sendto function

I am trying to send raw bits from a boost::dynamic_bitset with the Winsock2 sendto function.我正在尝试使用 Winsock2 sendto function 从 boost::dynamic_bitset 发送原始位。 MS documentation shows that sendto uses const char * type for the buffer parameter. MS 文档显示 sendto 使用 const char * 类型作为缓冲区参数。 How do I send only the raw bits stored in the dynamic_bitset?如何仅发送存储在 dynamic_bitset 中的原始位? I don't know how to cast or manipulate the dynamic_bitset so that it can be used in the sendto function.我不知道如何转换或操作 dynamic_bitset 以便它可以在 sendto function 中使用。

Here are some relevant lines from my program:以下是我的程序中的一些相关行:

#include <WinSock2.h>
#include <WS2tcpip.h>
#include <system_error>
#include <boost/dynamic_bitset/dynamic_bitset.hpp>
#pragma comment(lib, "ws2_32.lib")
using boost::dynamic_bitset;

dynamic_bitset<> getDynamicBitset() {
    //code to return a dynamic_bitset here
}
//create a dynamic bitset from a function
dynamic_bitset<> db1 = getDynamicBitset(); 

//manipulation of dynamic_bitset needed here to make it work in sendto as the buffer parameter

int ret = sendto(sock, buffer, len, flags, reinterpret_cast<SOCKADDR*>(&address), sizeof(address));

I am using the sample code from Peter R here: How do I receive udp packets with winsock in c++?我在这里使用 Peter R 的示例代码: 如何在 c++ 中接收带有 winsock 的 udp 数据包?

Also, my question is related to this, but I'm using C++ and not C.另外,我的问题与此有关,但我使用的是 C++ 而不是 C。 Sending a structure in the sendto() function - C language 在 sendto() function - C 语言中发送结构

I'm new to C++ and barely understand pointers and type manipulation.我是 C++ 的新手,几乎不了解指针和类型操作。

Thanks.谢谢。

I've implemented serialization for dynamic_bitset before: How to serialize boost::dynamic_bitset?我之前已经为 dynamic_bitset 实现了序列化: 如何序列化 boost::dynamic_bitset?

You can use that or a similar technique based on the same interfaces:您可以使用该技术或基于相同接口的类似技术:

template <typename Block, typename Alloc>
std::string to_binary_string(boost::dynamic_bitset<Block, Alloc> const& bs) {
    uint32_t const num_bits = bs.size();
    auto const num_blocks = div_roundup(num_bits, sizeof(Block)*CHAR_BIT);

    // prepare zeroed output buffer
    std::string buf(sizeof(num_bits) + num_blocks * sizeof(Block), '\0');

    // write size prefix 
    std::memcpy(buf.data(), &num_bits, sizeof(num_bits));

    // write block data
    if (num_bits > 0) { // mustn't pass nullptr to src argument of memcpy
        auto b = reinterpret_cast<Block*>(buf.data() + sizeof(num_bits));
        to_block_range(bs, b);
    }
    return buf;
}

Which you could send like:您可以发送如下:

std::string buf = to_binary_string(my_bitset);

int ret = sendto(sock, buf.data(), buf.size(), flags, reinterpret_cast<SOCKADDR*>(&address), sizeof(address));

The analogous deserialization code:类似的反序列化代码:

template <typename Block, typename Alloc>
void from_bytes(std::string_view buf, boost::dynamic_bitset<Block, Alloc>& bs) {
    // read the size prefix
    uint32_t num_bits;
    if (buf.size() < sizeof(num_bits)) {
        throw std::length_error("from_bytes");
    }
    std::memcpy(&num_bits, buf.data(), sizeof(num_bits));

    // shift buf to only cover the actual bit data
    buf = buf.substr(sizeof(num_bits));

    // read the bits as blocks
    bs.resize(num_bits);
    if (buf.size() % sizeof(Block) != 0) {
        throw std::length_error("from_bytes");
    }
    auto b = reinterpret_cast<Block const*>(buf.data());
    auto e = reinterpret_cast<Block const*>(buf.data() + buf.size());
    size_t const num_blocks = std::distance(b, e);
    
    // sanity checks block count vs num_bits
    if (num_blocks != div_roundup(num_bits, sizeof(Block)*CHAR_BIT)) {
        throw std::length_error("from_bytes"); // num_blocks doesn't match num_bits
    }

    from_block_range(b, e, bs);
    bs.resize(num_bits);
}

Live Demo现场演示

Disclaimer:免责声明:

  • Portability is NOT addressed here.可移植性不在此处讨论。 If you send data across systems using different native byte orderings, the behaviour is unspecified, even though care has been taken to not BLOW UP, the data would be wrong even in the extremely unlikely event that the sizes would add up.如果您使用不同的本机字节顺序跨系统发送数据,则行为是未指定的,即使已注意不要 BLOW UP,即使在极不可能的情况下,数据也会出错,即使大小加起来也是如此。
  • Similarly, no guarantees are made when the deserialized type doesn't exactly match the serialized type in terms of Block type.同样,当反序列化类型与块类型的序列化类型不完全匹配时,也无法保证。

That aside, the program tests edge cases and runs clean under ASAN/UBSAN.除此之外,该程序测试边缘情况并在 ASAN/UBSAN 下干净运行。

Live On Coliru住在科利鲁

#include <boost/dynamic_bitset.hpp>
#include <climits>      // CHAR_BIT
#include <string>
#include <string_view>
// demo output
#include <iostream>

static inline size_t div_roundup(size_t p, size_t q) {
    // quick&dirty, see https://stackoverflow.com/a/926806/85371
    return (p+q-1)/q;
}

template <typename Block, typename Alloc>
std::string to_binary_string(boost::dynamic_bitset<Block, Alloc> const& bs) {
    uint32_t const num_bits = bs.size();
    auto const num_blocks = div_roundup(num_bits, sizeof(Block)*CHAR_BIT);

    // prepare zeroed output buffer
    std::string buf(sizeof(num_bits) + num_blocks * sizeof(Block), '\0');

    // write size prefix 
    std::memcpy(buf.data(), &num_bits, sizeof(num_bits));

    // write block data
    if (num_bits > 0) { // mustn't pass nullptr to src argument of memcpy
        auto b = reinterpret_cast<Block*>(buf.data() + sizeof(num_bits));
        to_block_range(bs, b);
    }
    return buf;
}

template <typename Block, typename Alloc>
void from_bytes(std::string_view buf, boost::dynamic_bitset<Block, Alloc>& bs) {
    // read the size prefix
    uint32_t num_bits;
    if (buf.size() < sizeof(num_bits)) {
        throw std::length_error("from_bytes");
    }
    std::memcpy(&num_bits, buf.data(), sizeof(num_bits));

    // shift buf to only cover the actual bit data
    buf = buf.substr(sizeof(num_bits));

    // read the bits as blocks
    bs.resize(num_bits);
    if (buf.size() % sizeof(Block) != 0) {
        throw std::length_error("from_bytes");
    }
    auto b = reinterpret_cast<Block const*>(buf.data());
    auto e = reinterpret_cast<Block const*>(buf.data() + buf.size());
    size_t const num_blocks = std::distance(b, e);
    
    // sanity checks block count vs num_bits
    if (num_blocks != div_roundup(num_bits, sizeof(Block)*CHAR_BIT)) {
        throw std::length_error("from_bytes"); // num_blocks doesn't match num_bits
    }

    from_block_range(b, e, bs);
    bs.resize(num_bits);
}

int main() {
    ::srand(::time(0)); // extremely lazy bad random, sue me

    for (auto bits = 0; bits < 128; ++bits) {
        boost::dynamic_bitset<> my_bitset(bits), roundtrip;

        for (size_t bit = 0; bit < my_bitset.size(); ++bit)
            my_bitset.set(bit, rand()%2);

        from_bytes(to_binary_string(my_bitset), roundtrip);

        std::cout << "{" << roundtrip << "} " << (roundtrip == my_bitset? "OK":"ERROR") << std::endl;
    }
}

Printing:印刷:

{} OK
{0} OK
{11} OK
{001} OK
{0010} OK
{01000} OK
{110011} OK
{0101011} OK
{01101101} OK
{101011011} OK
{1011100010} OK
{11100100110} OK
{110010010000} OK
{0011100110110} OK
{11100110110001} OK
{111101110011011} OK
{1011101100011011} OK
{10101000000110111} OK
{000000110100111111} OK
{0110001110100001011} OK
{11111111010010010110} OK
{010011100110111000011} OK
{0110011101111000111000} OK
{10011100110001001110101} OK
{011001001100011111010011} OK
{1101010010110100000100101} OK
{01101111001100100010111110} OK
{010101111001011111100011000} OK
{0101111001111001000001011011} OK
{10011101100111110110110001010} OK
{000001110000100011000011101000} OK
{1101010001101101111001001110000} OK
{11111010100111110010101111110010} OK
{110010101001101110000001011101110} OK
{1010100100010000011011011010000111} OK
{11101101111011011010110101101010000} OK
{110000101010100111010111011110100010} OK
{1000111110000001111010110000001111010} OK
{00010010011001111101101110101111000000} OK
{000000011000001100101000111110000111101} OK
{1000111111000000000111101110111101100010} OK
{01001110000011011100111110100100010111011} OK
{001000011101111001110111110000110100011001} OK
{0011010001000110100101000010110000101101001} OK
{01110111010111101000011110110011011110110101} OK
{111001000011011110001100000111001000001101010} OK
{1110001101010100101110100111001010100111111001} OK
{00110110011111110001110111110101101010100000110} OK
{101000100110100111001000110111010101101011000011} OK
{0011111001111000011010110110111110111011001101000} OK
{00011100110101100011000001010000111001011001111111} OK
{100101100001101111011001000101110100111110000100001} OK
{1110101000000100001111100111101101111100100011111111} OK
{00001010100111101001000100010111101101100101000001110} OK
{110101000110000011000100000001100100111101001100110011} OK
{1001111110001011100010011110001011010111101010101100100} OK
{00101001010011101000100110011011110101100110000110100010} OK
{010101000111011001001010011001010110111110101011001100100} OK
{0101100010000001010001110011001100000001011101101010110000} OK
{01000111001101100011000010010010111010010010111101101001010} OK
{000111101101111000011101101101101101100001011110111000001000} OK
{0111101011101011101000011001010000011001010111001001111000011} OK
{01000100010000000110001110110010110100001000001011110000010011} OK
{110100101010111101010010011100110000110100001010110100110001011} OK
{0111110001111011011001110000101100111011010000000101111010000111} OK
{01101000000101000000010010010100010101000110100011001010011011011} OK
{110111111011010011011001001011000100010000100001001000000111110011} OK
{0000111000100111101000000001111000011100000101010100001101111101111} OK
{11100101011110110110101100100100110110110110000000000101000000000011} OK
{111011000011111101100101001010010010101110001001100110111100101011101} OK
{1001110011100111010010110011010111111001100110010011010100101000010010} OK
{01011111001100011100000000011100000111010111001111100001100110001111110} OK
{010010111000101000111100000000010011111110010110011110000000000000001100} OK
{1101010011010110010100000100100110100100100110011100011010000001000001011} OK
{10100101001110110001011010010101100100110100011011001000010110100001101010} OK
{101010100011101100111000111001011011010111000101101011111011000001010111110} OK
{1011011101011011000101101101000110011001001001110101010010001010111000101011} OK
{01100101111100011110101000001010111101011011100101111000101110011011110011100} OK
{111100111010011100010111101010110101110000100111011001001111001100001011111110} OK
{0000010110001101001001110010011011010111100010100001111010100000100000101010010} OK
{10010100010000110101000000101001011011001001000110110110110001000001001000011011} OK
{011011101100001101001110111110000111010111010011001100100010011111110000101101000} OK
{0011001100110110111111101010011111010001000001110001010000101110111100100010111101} OK
{10001101001110001000001110110011111010010111100101011100111110010100010111100001010} OK
{111100011111110011011001001111101111110001010100010000001101000000101001111110011000} OK
{1001100110101000000110001000101010100101110100011100100010111111010101101001110000011} OK
{11000111100001000001001010010011010101100100101100001100101110010100000000000111100000} OK
{011011101010011001000000101101100011010110001000111010100001111000111001101011110111110} OK
{1011100111101110001111011101111010011100111111111110011010010000111101100000110111110000} OK
{11010010100011011010011111101011100101010100110100101001010011100011100001001000010001100} OK
{101100101110110110010010010001000010101100101010000110000100101111110100010111010111010000} OK
{1001100111111100000101011010100111101010000110010100100111011001010101111010100000000110011} OK
{11001000001101011000100011101111000001110011000100010011011011110010110001111001000101000010} OK
{010101110110011011001001111010100001101010110101001101010100110111011101001110111011111111001} OK
{0000001100010100101010000011000000100110011001011111101110100111011110100011011101001011001111} OK
{11101001010111000101001110011001010000000110010110011010100001000010011010010010010110110110100} OK
{100001001010100100000100111100101100000111111010110010101101000110010110010110011111110010111010} OK
{0110011101101011110011100101100110111110011110110001100101011000101110110001011110100000001010101} OK
{11111011101101010010010000101110000111011011001010001000000111101110110001000101110100110101001100} OK
{101001001001010101110010000100001000001101111111010000000110100111110001111010100100001001100100100} OK
{1010011111100001100101101110111001110011110100000100100100110011101110001000010000100001011101001101} OK
{10101011111010101101011101110010101111010001100011111000110011111011101110101110011011010111110011010} OK
{101001011011011011111101011110110000010001000011001011111100011000001100111100001000101111101000110100} OK
{1100001111000101010001010010000110011001111111011101100011111010100011110011011001001110010100111101010} OK
{01110111101110010010110110011011100101001010011010110010000011100111111101010110110001000111101011001011} OK
{111110001010000011111101001011100010111001001110001101001011100010111001011001111110001110111000010001010} OK
{1000110001111101001001100010011101011011000000001010111001111001100001001000101111001011010000011100100110} OK
{01101100101011110001001001101001110100111100111101000100010111101011000101101110101011010100011111110101111} OK
{100011010110010100001100010011111100101010011010110101001010000100011100011110000110111101000011011110010111} OK
{0001110100111110010010100101000111111101101110010011100110111101111001111111100101100000101110011011000001101} OK
{10000101011100100101100111111000010100011100010101111000001101010011111010011011011000110011000100110100101000} OK
{100110110011000000010000100011100010010101110000111010010101011000110101111101110011011101001011001101010001010} OK
{1001010100011011000111111111111001011010000001110100011100001101000001000010101000111110110010100101101111111111} OK
{00111000110111101110100111000110101111111101101100011111111110101010101001000000110000111101101111010011100011011} OK
{111100000100010001011010111001111111010111001101000100010011010110100111011010111101001110010001001111100110110010} OK
{1111110110110111110000001110010010100011000101001001111010001001111101111100000011000101001001001101000110000001100} OK
{11110101001111001100101001010100101110100011000101110001101101101110111101010101111011010100000110100011111011010101} OK
{100111000001000011100001011000001100100010101011110110001100010100001011111011000011100110011001101110011111101000101} OK
{1110110110010100001000101001001110100000110010110011110001111111110011111010000010111101001000110010011111001111101000} OK
{00000101100100000111110000100101010100101000011000111010110110111100111101111110110101100011101101011000000001001110111} OK
{010111011011000010001010010100010110001001101101101101001011010001000010010000000111011100100110101011001000001011011000} OK
{0011011110010110010111101101111100111110000010111101010001101111101101101001001000101101101001110000110000000110100010010} OK
{00001001010011101011011010010000000011000110011100000101111000100101111110101111100100011110100101011101101111100011100101} OK
{001011011110110000011010101000001001100100011001000100110100100111100101100010111101001010101100100100011010111010000101100} OK
{1111110110100111101011110100111011000001001111111010100011110001100100010010110110111110111100001011101000000100100000100100} OK
{01110000101110010101010110100001010010101010001111110100010111000011101000111010101111001011100111000011111011110011101011100} OK
{001100001010111010111001111011011000100100110010110001010000001110000001000110010101101000111110010101001010101100010111100011} OK
{1100011010110110001110101000110011110110010011010101110001010111110010000110011111110101111010110001010100110010000101001110011} OK

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

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