【问题标题】:How to convert received bytes in Boost C++ to a unsigned int and to a vector of unsigned int如何将 Boost C++ 中接收到的字节转换为无符号整数和无符号整数向量
【发布时间】:2020-07-17 12:06:19
【问题描述】:

我正在通过 Python TCP Socket 向用 Boost C++ 编写的客户端发送一个无符号整数。 我想知道如何将 Boost C++ 套接字中接收到的字节转换为无符号整数。

Python 套接字服务器

import socket
import struct

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    print("listening..")
    conn, addr = s.accept()
    with conn:
        print('Connected by', addr)

        # SENDING 10 AS AN UNSIGNED INTEGER
        conn.send(struct.pack("I",10))

C++ Boost 客户端套接字

#include <boost/asio/local/stream_protocol.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>

using namespace std;

// CREATE SOCKET
boost::asio::io_service io_context;
boost::asio::streambuf sb;
boost::system::error_code ec;
boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 10000);
boost::asio::ip::tcp::socket socket(io_context);
socket.connect(ep);

// READ 4 BYTES
boost::asio::read(objSocket, sb,boost::asio::transfer_exactly(4), ec))

cout << "\nreceived: '" << &sb << "'\n";

// CONVERT 4 BYTES TO UNSIGNED INT
boost::asio::streambuf::const_buffers_type bufs = sb.data();

string str(boost::asio::buffers_begin(bufs), boost::asio::buffers_begin(bufs) + sb.size());

sb.consume(sb.size());

std::stringstream sstr(str);

unsigned int receivedInt = 0;

sstr >> receivedInt;

cout << "\nReceivedInt: "<< length;

PS:C++ 客户端接收到数据(4 字节),但我无法将其转换为 uint。

以及如何将字节转换为无符号整数向量?

提前谢谢你!

【问题讨论】:

    标签: python c++ sockets boost data-conversion


    【解决方案1】:

    在 Python 端,您没有为字节流指定字节顺序。所以它取决于机器,它可以是 little-endianbig-endian。这可能会导致问题。

    您可以通过以下方式强制发送字节流,例如在 little-endian 中:

    conn.send(struct.pack("<I",10))    # added < 
    

    在 C++ 中,通过调用 sstr &gt;&gt; receivedInt,您可以执行 格式化 数据读取。如果您的流将“10”作为字符串保存 - 2 个字符,它可能会起作用,但您的流包含 4 个字节 - 10 的二进制表示为十进制。您只需将所有字节的值合并到unsigned int,这很容易,因为您知道字节的顺序:

    boost::asio::streambuf::const_buffers_type bufs = sb.data();
    string str(boost::asio::buffers_begin(bufs), boost::asio::buffers_begin(bufs) + sb.size());
    sb.consume(sb.size());
    uint32_t received = 
        (str[0] & 0xFF) 
      | (str[1] << 8) & 0xFF00 
      | (str[2] << 16) & 0xFF0000
      | (str[3] << 24);
    std::cout << received << std::endl;  // 10 
    

    数据以 little-endian 顺序发送,因此在将其合并到 uint32 时,数据必须像这样移动:

    [str[3] | str[2] | str[1] | str[0]]
    

    在移动 char 被提升为 int 并扩展一点符号之前,因此您必须使用适当的掩码执行按位 AND 将最左边的位设为零。

    【讨论】:

    • 感谢您的回答,我刚刚尝试了您的解决方案,当我在 C++ 端发送 struct.pack("
    • 很好,非常感谢,它成功了!您能否简单解释一下为什么我们要从缓冲区转换为字符串再转换为整数。有没有办法直接从缓冲区转换为整数?
    • @Hangon 最简单的方法是定义uint32_t received,然后为这个整数创建一个缓冲区:boost::asio::read(socket, boost::asio::buffer(&amp;received,4),ec);。这已经足够了。 4 个字节将直接读入received。但在这种情况下,您必须处理小/大端。对于 big-endian,recevied 的字节应该颠倒过来。
    猜你喜欢
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 2012-08-13
    • 2017-07-21
    • 1970-01-01
    • 2012-02-17
    • 1970-01-01
    相关资源
    最近更新 更多