Добрый день!
Разбираюсь с boost::asio и пытаюсь организовать отправку бинарных данных через TCP-сокет. Коды передатчика и приемника лежат ниже. Принцип такой что я ввожу HEX-строку, а она преобразуется в бинарник и отправляется на такой то адрес-порт. Но на приемнике почему доходя до байта со значением 0x0A строка обрезается, хотя я отправлял более длинную строку.
Как же организовать передачу любых данных с комбинацией байтов от 0x00 до 0xFF? Я ничего не нашел по этой проблеме, к сожалению.
Асинхронный приемник, взят код из документации
// 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();
}
Код передатчика, работает по принципу адрес порт и вставляем hex-строку, которая преобразуется в бинарник и отправляется.
// 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;
}