Answer the question
In order to leave comments, you need to log in
Boost::asio truncates binary data at character 0x0A received on a TCP socket. Why?
Good afternoon!
I understand with boost:: asio and I try to organize sending of binary data through TCP-socket. The transmitter and receiver codes are below. The principle is that I enter a HEX string, and it is converted into a binary and sent to such and such an address-port. But on the receiver, why, reaching the byte with the value 0x0A, the string is cut off, although I sent a longer string.
How to organize the transfer of any data with a combination of bytes from 0x00 to 0xFF? I didn't find anything on this issue, unfortunately.
Asynchronous receiver, code taken from documentation
// c++ transceiver.cpp -o transceiver -I./include -lboost_system -lpq -std=c++11
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <transceiver.hpp>
using namespace boost::asio;
using namespace boost::posix_time;
using namespace std;
io_service service;
transceiver transceiver;
#define MEM_FN(x) boost::bind(&self_type::x, shared_from_this())
#define MEM_FN1(x,y) boost::bind(&self_type::x, shared_from_this(),y)
#define MEM_FN2(x,y,z) boost::bind(&self_type::x, shared_from_this(),y,z)
class talk_to_client : public boost::enable_shared_from_this<talk_to_client>, boost::noncopyable {
typedef talk_to_client self_type;
talk_to_client() : sock_(service), started_(false) {}
public:
typedef boost::system::error_code error_code;
typedef boost::shared_ptr<talk_to_client> ptr;
void start() {
started_ = true;
do_read();
}
static ptr new_() {
ptr new_(new talk_to_client);
return new_;
}
void stop() {
if ( !started_) return;
started_ = false;
sock_.close();
}
ip::tcp::socket & sock() { return sock_;}
private:
void on_read(const error_code & err, size_t bytes) {
if ( !err) {
string msg(read_buffer_, bytes);
string response = "OK\n\r";
// Обрабатываем сообщение и генерируем ответ
if(transceiver.check(msg)) {
response = transceiver.run(msg);
}
do_write(response);
}
// Завершить соединение
//stop();
}
void on_write(const error_code & err, size_t bytes) {
do_read();
}
void do_read() {
async_read(sock_, buffer(read_buffer_), MEM_FN2(read_complete,_1,_2), MEM_FN2(on_read,_1,_2));
}
void do_write(const string & msg) {
copy(msg.begin(), msg.end(), write_buffer_);
sock_.async_write_some( buffer(write_buffer_, msg.size()), MEM_FN2(on_write,_1,_2));
}
size_t read_complete(const boost::system::error_code & err, size_t bytes) {
if ( err) return 0;
bool found = find(read_buffer_, read_buffer_ + bytes, '\n') < read_buffer_ + bytes;
// we read one-by-one until we get to enter, no buffering
return found ? 0 : 1;
}
private:
ip::tcp::socket sock_;
enum { max_msg = 1024 };
char read_buffer_[max_msg];
char write_buffer_[max_msg];
bool started_;
};
ip::tcp::acceptor acceptor(service, ip::tcp::endpoint(ip::tcp::v4(), 8001));
void handle_accept(talk_to_client::ptr client, const boost::system::error_code & err) {
client->start();
talk_to_client::ptr new_client = talk_to_client::new_();
acceptor.async_accept(new_client->sock(), boost::bind(handle_accept,new_client,_1));
}
int main(int argc, char* argv[]) {
bool init = transceiver.init();
if(init == false) {
return 0;
}
talk_to_client::ptr client = talk_to_client::new_();
acceptor.async_accept(client->sock(), boost::bind(handle_accept,client,_1)); // Включаем приемник
service.run();
}
// c++ send.cpp -o send -I./include -lboost_system -lpthread -std=c++11
#include <iostream>
#include <boost/asio.hpp>
using namespace std;
using boost::asio::ip::tcp;
enum { max_length = 1024 };
int main(int argc, char* argv[])
{
try
{
if (argc != 3)
{
cerr << "Usage: send <host> <port>\n";
return 0;
}
boost::asio::io_service io_service;
tcp::socket s(io_service);
tcp::resolver resolver(io_service);
boost::asio::connect(s, resolver.resolve({argv[1], argv[2]}));
cout << "Enter message in HEX: ";
char r[max_length];
cin.getline(r, max_length);
string hex = r;
int len = hex.length();
string msg;
string byte;
for(int i=0; i< len; i+=2)
{
byte = hex.substr(i, 2);
char chr = (char) (int)strtol(byte.c_str(), NULL, 16);
msg.push_back(chr);
}
boost::asio::write(s, boost::asio::buffer(msg.c_str(), msg.length()));
char reply[max_length];
size_t reply_length = boost::asio::read(s, boost::asio::buffer(reply, ytmax_length));
cout << "Reply is: ";
cout.write(reply, reply_length);
cout << "\n";
}
catch (exception& e)
{
cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
Answer the question
In order to leave comments, you need to log in
bool found = find(read_buffer_, read_buffer_ + bytes, '\n') < read_buffer_ + bytes;
read complete on 0x0a probably works?
See Wireshark what you are actually sending. Maybe the problem is not on the receiving side.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question