I'm sending via Python TCP Socket an unsigned integer to a client written in Boost C++. I would like to know how to convert the received bytes in the Boost C++ socket into an unsigned integer.
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 Client Socket
#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: The C++ client receives the data (4bytes) but I can't convert it to uint.
And how to convert bytes to a vector of unsigned int?
Thank you in advance!
At the Python side you don't specify byte order for your bytes stream. So it will depend on the machine, it could be little-endian or big-endian. It may lead to problems.
You can force bytes stream to be sent for example in little-endian by:
conn.send(struct.pack("<I",10)) # added <
In C++, by calling sstr >> receivedInt
you perform formatted reading of data. It could work if your stream held "10" as string - 2 characters, but your stream contains 4 bytes - binary representation of 10 as decimal. You have to just merge values of all bytes into unsigned int
, which is easy because you know the order of bytes:
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
Data is sent in little-endian order so when merging it into uint32 data must be shifted like this:
[str[3] | str[2] | str[1] | str[0]]
Before shifting char is promoted to be int with extending a bit of sign, so you have to perform bitwise AND with proper masks to zero most left bits.