19.3 Boost Asio 多线程通信

发布时间 2023-11-02 08:44:36作者: lyshark

多线程服务依赖于两个通用函数,首先boost::bind提供了一个高效的、简单的方法来创建函数对象和函数对象适配器,它的主要功能是提供了一种将函数和它的参数绑定到一起的方法,这种方法可以将具有参数的成员函数、普通函数以及函数对象转化为不带参数的函数对象。

当参数绑定后则下一步就需要使用多线程功能,Boost库中提供了boost::thread库,boost::thread可以用于创建线程、启动线程、等待线程执行结束以及线程间通信等多种操,有了这两个关键库那么我们只需要accept.accept(*sock)等待套接字上线,当有套接字上线后则自动创建MyThread子线程,使用该子线程维持会话,首先是服务端实现代码。

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>

using namespace boost::asio;

std::string addr = "127.0.0.1";

// 创建子线程
void MyThread(boost::shared_ptr<ip::tcp::socket> socket)
{
  // 获取当前IP信息
  std::string local_address = socket->local_endpoint().address().to_string();
  while (true)
  {
    try
    {
      if (addr == local_address)
      {
        char data[512];
        size_t len = socket->read_some(buffer(data));
        std::cout << data << std::endl;
      }
    }
    catch (boost::system::system_error e)
    {
      return;
    }
  }
}

int main(int argc, char* argv[])
{
  typedef boost::shared_ptr<ip::tcp::socket> socket_ptr;
  io_service service;

  // 绑定IP与端口地址
  ip::tcp::endpoint ep(ip::tcp::v4(), 6666);
  ip::tcp::acceptor accept(service, ep);

  while (true)
  {
    socket_ptr sock(new ip::tcp::socket(service));

    // 侦听套接字
    accept.accept(*sock);

    // 绑定套接字参数
    boost::function0<void> function = boost::bind(MyThread, sock);

    // 创建新的子线程
    boost::thread threading(function);
  }

  system("pause");
  return 0;
}

客户端代码如下所示,由于客户端无需实现多线程所以代码中只需要简单的调用socket.connect()链接到服务端,并调用write_some发送一条消息即可,代码如下图所示;

#include <iostream>
#include <string>
#include <boost/asio.hpp>

using namespace boost::asio;

int main(int argc, char *argv[])
{
  io_service io_service;
  ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1"), 6666);
  ip::tcp::socket socket(io_service);

  // 链接到服务端
  socket.connect(ep);

  char buffer[1024] = "hello lyshark";

  socket.write_some(boost::asio::buffer(buffer, 1024));

  system("pause");
  return 0;
}

运行上方服务端代码,然后开启三个客户端代码,读者可自行观察通信状态,此时三个客户端均实现了输出,如下图所示;