C
C
chimkiu2015-12-02 12:08:07
C++ / C#
chimkiu, 2015-12-02 12:08:07

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();
}


The transmitter code works on the principle of an address port and insert a hex string, which is converted into a binary and sent.
// 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

2 answer(s)
I
iv_k, 2015-12-02
@iv_k

bool found = find(read_buffer_, read_buffer_ + bytes, '\n') < read_buffer_ + bytes;
read complete on 0x0a probably works?

V
Vladimir Martyanov, 2015-12-02
@vilgeforce

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 question

Ask a Question

731 491 924 answers to any question