C++ 使用 Winsock2 sendto 函数发送 boost::dynamic_bitset

问题描述

我正在尝试使用 Winsock2 sendto 函数从 boost::dynamic_bitset 发送原始位。 MS 文档显示 sendto 使用 const char * 类型作为缓冲区参数。 如何仅发送存储在 dynamic_bitset 中的原始位?我不知道如何转换或操作 dynamic_bitset 以便它可以在 sendto 函数中使用。

以下是我的程序中的一些相关行:

#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));

在这里使用 Peter R 的示例代码How do I receive udp packets with winsock in c++?

另外,我的问题与此有关,但我使用的是 C++ 而不是 C。 Sending a structure in the sendto() function - C language

我是 C++ 新手,几乎不了解指针和类型操作。

谢谢。

解决方法

我之前已经为 dynamic_bitset 实现了序列化:How to serialize boost::dynamic_bitset?

您可以使用该技术或基于相同接口的类似技术:

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;
}

您可以发送的内容:

std::string buf = to_binary_string(my_bitset);

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

类似的反序列化代码:

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,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);
}

现场演示

免责声明:

  • 此处不涉及可移植性。如果您使用不同的本机字节顺序跨系统发送数据,则行为未指定, 即使已经注意不要爆炸,数据也会是 即使在尺寸会增加的极不可能的情况下也是错误的
  • 同样,当反序列化类型在块类型方面与序列化类型完全不匹配时,不做任何保证。

除此之外,程序测试边缘情况并在 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,b);
    }
    return buf;
}

template <typename Block,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;
    }
}

印刷:

{} 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