How to use boost::asio::async_write(socket_, boost::asio::buffer(data, size) to write an int value?

huangapple go评论79阅读模式
英文:

How to use boost::asio::async_write(socket_, boost::asio::buffer(data, size) to write an int value?

问题

I am trying to return an integer to the netcat(tcp) terminal, every time the message sent is Coop25, but this has generated a strange response on the terminal. The response is an instead of the integer and looks like this:

NETCAT TERMINAL:

Coop25
����

I have tried this function:

void tcp::tcp_session::do_write()
{ 
    std::array<int, 1> test{1};
    auto self(shared_from_this());
    boost::asio::async_write(socket_, boost::asio::mutable_buffer(test.data(), test.size),
        [this, self](boost::system::error_code ec, std::size_t /*length*/)
        {
          if (!ec)
          {
            do_read();
          }
        });
}

But when I try using some string this works:

std::string ret_mess_check{"blabla"}
const char* mess_to_reply = ret_mess_check.c_str();
do_write(mess_to_reply, strlen(mess_to_reply)); 

void tcp::tcp_session::do_write(const char* reply, std::size_t length)
{ 
    auto self(shared_from_this());
    boost::asio::async_write(socket_, boost::asio::buffer(reply, length),
        [this, self](boost::system::error_code ec, std::size_t /*length*/)
        {
          if (!ec)
          {
            do_read();
          }
        });
}

After @sehe's considerations, I am doing something like this:

in a .hpp file, declaring the mv num_status_{-1};

boost::array<int, max_length> num_status_{-1};

in a .cpp file, defining the do_write() function, like this:

void dac_sim::tcp::tcp_session::do_write()
{ 
    auto self(shared_from_this());
    boost::asio::async_write(socket_, boost::asio::buffer(num_status_),
        [this, self](boost::system::error_code ec, std::size_t /*length*/)
        {
          if (!ec)
          {
            do_read();
          }
        });
}

If I replace the member variable from an int to a string, everything works fine. With an int, the "����" still appears instead of -1 in this case.

英文:

I am trying to return an integer to the netcat(tcp) terminal, every time the message sent is Coop25, but this has generated a strange response on the terminal. The response is an instead of the integer and looks like this:

NETCAT TERMINAL:

Coop25
����

I have tried this function:

void tcp::tcp_session::do_write()
{ 
    std::array&lt;int, 1&gt; test{1};
    auto self(shared_from_this());
    boost::asio::async_write(socket_, boost::asio::mutable_buffer(test.data(), test.size),
        [this, self](boost::system::error_code ec, std::size_t /*length*/)
        {
          if (!ec)
          {
            do_read();
          }
        });
}

But when I try using some string this works:

std::string ret_mess_check{&quot;blabla&quot;}
const char* mess_to_reply = ret_mess_check.c_str();
do_write(mess_to_reply, strlen(mess_to_reply)); 

void tcp::tcp_session::do_write(const char* reply, std::size_t length)
{ 
    auto self(shared_from_this());
    boost::asio::async_write(socket_, boost::asio::buffer(reply, length),
        [this, self](boost::system::error_code ec, std::size_t /*length*/)
        {
          if (!ec)
          {
            do_read();
          }
        });
}

After @sehe's considerations, I am doing something like this:

in a .hpp file, declaring the mv num_status_{-1};

boost::array&lt;int, max_length&gt; num_status_{-1};

in a .cpp file, defining the do_write() function, like this:

void dac_sim::tcp::tcp_session::do_write()
{ 
    auto self(shared_from_this());
    boost::asio::async_write(socket_, boost::asio::buffer(num_status_),
        [this, self](boost::system::error_code ec, std::size_t /*length*/)
        {
          if (!ec)
          {
            do_read();
          }
        });
}

If I replace the member variable from an int to a string, everything works fine. With an int, the "����" still appears instead of -1 in this case.

答案1

得分: 1

你发送了 /buffers/。您的代码不是按照给定的方式编译。首先,test.size 是一个指向成员函数的指针。即使你的意思是 test.size(),它也只会发送1字节,因为test.size()返回1。另外,您在不需要可变性的情况下使用了 mutable_buffer。我会写两个表达式更简单,更少出错:

void tcp::tcp_session::do_write(std::string_view reply) {
    async_write(socket_, asio::buffer(reply),
                [this, self = shared_from_this()](error_code ec, size_t /*length*/) {
                    if (!ec)
                        do_read();
                });
}

void tcp::tcp_session::do_write() {
    async_write(socket_, asio::buffer(test),
                [this, self = shared_from_this()](error_code ec, size_t /*length*/) {
                    if (!ec)
                        do_read();
                });
}

你甚至可以将这两个结合起来写成通用的形式:

void tcp::tcp_session::do_write(auto const& reply) {
    async_write(socket_, asio::buffer(reply),
                [this, self = shared_from_this()](error_code ec, size_t /*length*/) {
                    if (!ec)
                        do_read();
                });
}

它可以适用于字符串,array<int, 1>std::vector<myComplicatedPodType>,甚至 double[32] 等等。

你甚至可以将它们组合成一个缓冲区序列:

async_write(socket_, std::array{asio::buffer(test), asio::buffer(ret_mess_check)},
            [this, self = shared_from_this()](error_code ec, size_t /*length*/) {
                if (!ec)
                    do_read();
            });

附注

关于问题代码还有一件事情需要注意,您绝不能在异步操作中使用局部变量(比如您的 test 数组),因为它会导致未定义行为,因为缓冲区引用了在异步操作完成之前生命周期已结束的对象。

英文:

You send /buffers/. Your code doesn't compile as given. For starters test.size is a pointer-to-member-function. Even if you meant test.size() then it would only send 1 byte, because test.size() returns 1. Also, you're using mutable_buffer when you don't need mutability. I'd write both incantations much simpler and much less error-prone:

void tcp::tcp_session::do_write(std::string_view reply) {
    async_write(socket_, asio::buffer(reply),
                [this, self = shared_from_this()](error_code ec, size_t /*length*/) {
                    if (!ec)
                        do_read();
                });
}

void tcp::tcp_session::do_write() {
    async_write(socket_, asio::buffer(test),
                [this, self = shared_from_this()](error_code ec, size_t /*length*/) {
                    if (!ec)
                        do_read();
                });
}

You can even combine the two generically:

void tcp::tcp_session::do_write(auto const&amp; reply) {
    async_write(socket_, asio::buffer(reply),
                [this, self = shared_from_this()](error_code ec, size_t /*length*/) {
                    if (!ec)
                        do_read();
                });
}

And it would work for strings, array&lt;int, 1&gt;, std::vector&lt;myComplicatedPodType&gt; and even double[32] etc. etc.

You can even combine them in a buffer-sequence:

async_write(socket_, std::array{asio::buffer(test), asio::buffer(ret_mess_check)},
            [this, self = shared_from_this()](error_code ec, size_t /*length*/) {
                if (!ec)
                    do_read();
            });

Side Note

Another thing to note about the question code that you MUST NOT use a local variable (like your test array) in an asynchronous operation, because it causes Undefined Behaviour because the buffer refers to an object whose lifetime ends before the asynchronous operation completes.

huangapple
  • 本文由 发表于 2023年6月29日 23:33:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76582554.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定