Как преобразовать полученные байты в Boost C ++ в беззнаковое целое и в вектор беззнакового целого - PullRequest
0 голосов
/ 05 апреля 2020

Я отправляю через Python TCP Socket целое число без знака клиенту, написанному на Boost C ++. Я хотел бы знать, как преобразовать полученные байты в сокете Boost C ++ в целое число без знака.

Python Socket Server

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.

А как преобразовать байты в вектор без знака int?

Заранее спасибо!

1 Ответ

1 голос
/ 05 апреля 2020

На стороне Python вы не указываете порядок байтов для вашего потока байтов. Так что это будет зависеть от машины, это может быть little-endian или big-endian . Это может привести к проблемам.

Вы можете принудительно отправить поток байтов, например, в little-endian :

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

В C ++, вызвав sstr >> 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 с расширением немного знака, поэтому вы должны иметь выполнять побитовое И с надлежащими масками для обнуления большинства левых битов.

...