@chimkiu

Boost::asio обрезает бинарные данные на символе 0x0A принимаемые на TCP сокете. Почему?

Добрый день!

Разбираюсь с 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;
}
  • Вопрос задан
  • 519 просмотров
Пригласить эксперта
Ответы на вопрос 2
@iv_k
bool found = find(read_buffer_, read_buffer_ + bytes, '\n') < read_buffer_ + bytes;

read complete по 0x0a срабатывает наверное?
Ответ написан
Комментировать
@vilgeforce
Раздолбай и программист
Смотрите Wiresharkом что вы реально отправляете. Может, проблема не на приемной стороне.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы