将async_write回调作为另一个类实例的成员函数进行提升

时间:2016-02-27 23:46:50

标签: c++ boost boost-asio

我有一个协议结构,其中一个类负责协议状态(Protocol),另一个类负责发送和接收消息(Comm)。 我在异步模式下使用boost:asio

所以我有以下代码结构:

#include <string>
#include <iostream>

#include "boost/asio.hpp"
#include "boost/bind.hpp"

class Comm {
public:
    Comm::Comm();
    void SendMessage(std::string message, void (callback) (const boost::system::error_code& errorCode, std::size_t bytesTranferred));

private:
    boost::asio::io_service ioService;
    std::shared_ptr<boost::asio::ip::tcp::socket> mySocket;
};

Comm::Comm()
{
    boost::asio::ip::tcp::resolver resolver(ioService);
    boost::asio::ip::tcp::resolver::query query("192.168.0.1");
    boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
    mySocket->connect(*iterator);
}
void Comm::SendMessage(std::string message, void (callback) (const boost::system::error_code& errorCode, std::size_t bytesTranferred))
{
    mySocket->async_send(boost::asio::buffer(message.c_str(), message.length()), boost::bind(&callback)); // <<< ERROR HERE

}

class Protocol {

public: 
    void SendMessage(std::string message); 
    void SendMessageHandler(const boost::system::error_code& errorCode, std::size_t bytesTranferred);

private:
    Comm channel;
};

void Protocol::SendMessage(std::string message)
{
    channel.SendMessage(message, &SendMessageHandler); // <<< ERROR HERE 
}

void Protocol::SendMessageHandler(const boost::system::error_code& errorCode, std::size_t bytesTranferred)
{
    if (!errorCode)
        std::cout << "Send OK" << std::endl;
    else
        std::cout << "Send FAIL." << std::endl;
}

如图所示,我需要将async_send的回调作为调用者类的非静态函数,因此我必须在SendMessage中传递回调函数并将其用作async_send中的参数。

这两个陈述都没有编译。我尝试了变化,但我找不到发生了什么。

帮助表示赞赏。

1 个答案:

答案 0 :(得分:1)

使用binding to class method尝试这样的事情:

void Comm::SendMessage(std::string message, boost::function< void(const boost::system::error_code& , std::size_t) > callback )
{
    mySocket->async_send(boost::asio::buffer(message.c_str(), message.length()), callback);
}
...//later
channel.SendMessage(message, boost::bind(&Protocol::SendMessageHandler, this) );

注意/更重要的是,这里有大量无法修复的错误:

  • 您按值std::string message多次 - 它会复制内容。
  • Comm::SendMessage使用本地message对象,在异步操作完成之前将被销毁(boost::asio::buffer不会复制内容)。
  • 很难使用2个或更多Comm个对象,因为每个对象都有自己的ioService(您无法同时运行它们)
  • 没有shared_ptr或任何其他控制对象生命周期的功能:SendMessageHandler已被销毁后,您可以调用Protocol
  • Protocol无法控制写并行性,多个SendMessage调用可能导致将混合缓冲区写入套接字,这可以/将通过网络发送完整的垃圾。
  • 更致命/轻微的问题,没有必要搜索它们。

考虑将asio examples中的一个作为基本使用模式。