Boost实现简易服务器和客户端示例

简介: Boost实现简易服务器和客户端示例

写在前面

最近项目中有用到boost库,这里就记录下学习过程。

一、什么是boost库

Boost是一个功能强大 , 构造精良 , 跨越平台 , 代码开源 , 完全免费的 C ++ 程序库。共包含 160 余个库 / 组件 , 涵盖字符串与文本处理、容器、迭代器、算法、图像处理、模板元编程、并发编程等多个领域。 由 c ++ 标准委员会成员发起倡议并建立 boost 社区 , C ++11 标准库中三分之二来自 boost , 并且将来还会有更多的库进入 c ++ 标准库 , 因此 boost 是一个 c ++ " 准 " 标准库。支持现有的所有操作系统。

二、使用boost实现socket客户端与服务端

2.1 客户端代码

BoostClient.h

#include "BoostClient.h"
BoostClient::BoostClient(io_service& service, ip::tcp::endpoint ep):m_ios(service)
{
    pSocket.reset(new ip::tcp::socket(service));
    boost::system::error_code ec;
    pSocket->connect(ep, ec);
    if(ec)
    {
        std::cerr << "Error connecting to server: " << ec.message() << std::endl;
        bConnected = false;
        return;
    }
    bConnected = true;
}
void BoostClient::AsyncRecvMessage()
{
    memset(data_.data(), 0, sizeof(data_));
    pSocket->async_read_some(buffer(data_), [this](const boost::system::error_code &ec, size_t bytes) {
    if(!ec)
    {
        std::cout<<"recv size:"<<bytes<<std::endl;
        std::cout<<"recv data:"<<data_.data()<<std::endl;
        AsyncRecvMessage();
    }
    else if(ec == error::eof)
    {
        // 断开连接
        bConnected = false;
        std::cout<<"disconnected !"<<std::endl;
    }
    else
    {
        std::cout<<"read error: "<<ec.message()<<std::endl;
    }
    });
}
void BoostClient::AsyncSendMessage(std::string message)
{
    if(message.empty() || !bConnected)
    {
        return;
    }
    async_write(*pSocket, buffer(message.c_str(), message.size()), [this](const boost::system::error_code &ec, size_t writed_bytes)
  {
    if (!ec)
    {
    }
        else
        {
            std::cout <<"send error:"<<ec.message() << std::endl;
            bConnected = false;
        }
  });
} 

BoostClient.h

#include <iostream>
#include <array>
#include <boost/asio.hpp>
using namespace boost::asio;
class BoostClient
{
public:
    BoostClient(io_service& service, ip::tcp::endpoint ep);
    void AsyncRecvMessage();
    void AsyncSendMessage(std::string message);
private:
    bool bConnected;
    // io_service &ios;
    io_service &m_ios;
    std::shared_ptr<ip::tcp::socket> pSocket;
    std::array<char, 1024> data_;
};

main.cpp

#include <iostream>
#include "BoostClient.h"
#define DEFAULT_SERVER_IP   "127.0.0.1"
#define DEFAULT_SERVER_PORT 8888
int main(int argc, char **argv)
{
    ip::tcp::endpoint ep(ip::address_v4::from_string(DEFAULT_SERVER_IP), DEFAULT_SERVER_PORT);
    io_service service;
    BoostClient client(service, ep);
    client.AsyncSendMessage("hello, server this is message.");
    client.AsyncRecvMessage();
    service.run();
    return 0;
}

CMakeLists.txt\

cmake_minimum_required(VERSION 3.0.0)
project(boost_client)
add_executable(boost_client 
  main.cpp BoostClient.cpp
)
#boost库检查
find_package(Boost 1.77.0 COMPONENTS context thread date_time program_options filesystem system coroutine log_setup log REQUIRED)
if(Boost_FOUND)
  include_directories(${Boost_INCLUDE_DIRS})
  link_directories(${Boost_LIBRARY_DIRS})
else()
  message("check boost lib failed!")
endif()
target_link_libraries(${PROJECT_NAME} 
  pthread libboost_thread.a  libboost_filesystem.a libboost_log_setup.a libboost_log.a libboost_locale.a
  libboost_coroutine.a  libboost_context.a
)
2.2 服务端代码

BoostServer.h

#include <memory>
#include <iostream>
#include <array>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <atomic>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
using namespace boost::asio;
typedef std::function<void(void)> Callback_Close;
typedef std::function<void(std::string)> Callback_SendMessage;
// 接收客户端发送来的消息
class Session_Recv : public std::enable_shared_from_this<Session_Recv>
{
public:
    Session_Recv(ip::tcp::socket socket);
    void SetClose(Callback_Close pClose);
    void SetMsg_Ntf(Callback_SendMessage pMsg);
    void async_read();
    bool GetState();
private:
    ip::tcp::socket socket_;
    std::array<char, 1024> data_;
    std::atomic<bool> connected_;
    Callback_Close ptr_close_;
    Callback_SendMessage ptr_message_;
};
// 向客户端发送消息
class Session_Send : public std::enable_shared_from_this<Session_Send>
{
public:
    Session_Send(ip::tcp::socket socket);
    void SetClose(Callback_Close pClose);
    void async_send(std::string message);
    bool GetState();
private:
    ip::tcp::socket socket_;
    std::atomic<bool> connected_;
    Callback_Close ptr_close_;
};
// 服务器 接收port_recv端口发来的数据    向port_send端口发送数据
class BoostServer
{
public:
    BoostServer(boost::asio::io_context &ctx, short port_recv, short port_send, std::string ip_recv = "", std::string ip_send = "");
    void Close_Session_Recv();
    void Close_Session_Send();
    void GetContent(std::string content);
private:
    void Async_Accept_Recv();
    void Async_Accept_Send();
    void SendMessage();
private:
    std::shared_ptr<std::thread> ptr_Thread_Msg;
    std::shared_ptr<boost::asio::ip::tcp::acceptor> Acceptor_Recv_;
    std::shared_ptr<boost::asio::ip::tcp::acceptor> Acceptor_Send_;
    std::shared_ptr<ip::tcp::endpoint> ptr_Recv_ep;
    std::shared_ptr<ip::tcp::endpoint> ptr_Send_ep;
    std::vector<std::shared_ptr<Session_Recv>> clients_recv;
    std::vector<std::shared_ptr<Session_Send>> clients_send;
    std::queue<std::string> Array_messages;
    std::atomic<bool> bStopSend;
    std::mutex mtx;
};

BoostServer.cpp

#include "boostServer.h"
Session_Recv::Session_Recv(ip::tcp::socket socket):socket_(std::move(socket))
{
    connected_ = true;
    ptr_close_ = nullptr;
    ptr_message_ = nullptr;
}
void Session_Recv::SetClose(Callback_Close pClose)
{
    ptr_close_ = pClose;
}
void Session_Recv::SetMsg_Ntf(Callback_SendMessage pMsg)
{
    ptr_message_ = pMsg;
}
void Session_Recv::async_read()
{
    auto self(shared_from_this());
    memset(data_.data(), 0, sizeof(data_));
  // 读操作完成时回调该函数, 读取到一些数据就会触发回调
  socket_.async_read_some(buffer(data_), [this, self](const boost::system::error_code &ec, size_t bytes) {
      if (!ec)
      {
            if(ptr_message_)
            {
                ptr_message_(std::string(data_.data(), bytes));
            }
            std::cout << "size:"<< bytes<<std::endl;
            async_read();
        }
        else if(ec == error::eof)
        {
            // 断开连接
            std::cout <<"read disconnect:"<<ec.message() << std::endl;
            connected_ = false;
            if(ptr_close_)
            {
                ptr_close_();
            }
        }
        else
        {
            std::cout<<"read error:"<<ec.message()<<std::endl;
        }
  });
}
bool Session_Recv::GetState()
{
    return connected_;
}
Session_Send::Session_Send(ip::tcp::socket socket):socket_(std::move(socket))
{
    connected_ = true;
    ptr_close_ = nullptr;
}
void Session_Send::SetClose(Callback_Close pClose)
{
    ptr_close_ = pClose;
}
void Session_Send::async_send(std::string message)
{
    if(message.empty() || !connected_)
    {
        return;
    }
    auto self(shared_from_this());
    async_write(socket_, buffer(message.c_str(), message.size()), [this, self](const boost::system::error_code &ec, size_t writed_bytes)
    {
      if (!ec)
      {
      //  async_read();
      }
            else
            {
                std::cout <<"send error:"<<ec.message() << std::endl;
                connected_ = false;
                if(ptr_close_)
                {
                    ptr_close_();
                }
            }
    });
}
bool Session_Send::GetState()
{
    return connected_;
}
BoostServer::BoostServer(boost::asio::io_context &ctx, short port_recv, short port_send, std::string ip_recv, std::string ip_send)
{
    ptr_Thread_Msg.reset(new std::thread(std::bind(&BoostServer::SendMessage, this)));
    if("" == ip_recv)
    {
        ptr_Recv_ep.reset(new ip::tcp::endpoint(ip::tcp::v4(), port_recv));
    }
    else
    {
        ptr_Recv_ep.reset(new ip::tcp::endpoint(ip::address::from_string(ip_recv), port_recv));
    }
    Acceptor_Recv_.reset(new ip::tcp::acceptor(ctx, *ptr_Recv_ep));
    if("" == ip_send)
    {
        ptr_Send_ep.reset(new ip::tcp::endpoint(ip::tcp::v4(), port_send));
    }
    else
    {
        ptr_Send_ep.reset(new ip::tcp::endpoint(ip::address::from_string(ip_send), port_send));
    }
    Acceptor_Send_.reset(new ip::tcp::acceptor(ctx, *ptr_Send_ep));
    clients_recv.clear();
    clients_send.clear();
    Async_Accept_Recv();
    Async_Accept_Send();
}
void BoostServer::Async_Accept_Recv()
{
    Acceptor_Recv_->async_accept([this](boost::system::error_code ec, ip::tcp::socket socket)
        {
            if (!ec)
            {
                auto ptr = std::make_shared<Session_Recv>(std::move(socket));
                ptr->SetClose(std::bind(&BoostServer::Close_Session_Recv, this));
                ptr->SetMsg_Ntf(std::bind(&BoostServer::GetContent, this, std::placeholders::_1));
            ptr->async_read();
                clients_recv.push_back(ptr);
            }
            Async_Accept_Recv();
        });
}
void BoostServer::Async_Accept_Send()
{
    Acceptor_Send_->async_accept([this](boost::system::error_code ec, ip::tcp::socket socket)
        {
            if (!ec)
            {
                auto ptr = std::make_shared<Session_Send>(std::move(socket));
                ptr->SetClose(std::bind(&BoostServer::Close_Session_Send, this));
                clients_send.push_back(ptr);
            }
            Async_Accept_Send();
        });
}
void BoostServer::Close_Session_Recv()
{
    for(auto ptr = clients_recv.begin(); ptr != clients_recv.end();)
    {
        if (false == ptr->get()->GetState())
        {
            ptr->reset();
            clients_recv.erase(ptr);
            continue;
        }
        ptr++;
    }
    std::cout <<"Send_Data_Clients: "<<clients_recv.size()<<", Recv_Data_Clients: "<<clients_send.size()<< std::endl;
}
void BoostServer::Close_Session_Send()
{
    for(auto ptr = clients_send.begin(); ptr != clients_send.end();)
    {
        if(false == ptr->get()->GetState())
        {
            ptr->reset();
            clients_send.erase(ptr);
            continue;
        }
        ptr++;
    }
    std::cout <<"Send_Data_Clients: "<<clients_recv.size()<<", Recv_Data_Clients: "<<clients_send.size()<< std::endl;
}
void BoostServer::GetContent(std::string content)
{
    if(content.empty())
    {
        return;
    }
    if(mtx.try_lock())
    {
        Array_messages.push(content);
        mtx.unlock();
    }
}
void BoostServer::SendMessage()
{
    std::string message = "";
    bStopSend = false;
    while(!bStopSend)
    {
        if(mtx.try_lock())
        {
            if(!Array_messages.empty())
            {
                message = Array_messages.front();
                Array_messages.pop();
            }
            mtx.unlock();
        }
        if(!message.empty())
        {
            for(auto ptr = clients_send.begin(); ptr != clients_send.end(); ptr ++)
            {
                std::cout << "send message" << std::endl;
                ptr->get()->async_send(message);
            }
            message.clear();
            continue;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }
}

main.cpp

#include "boostServer.h"
#define DEFAULT_SERVER_IP   "127.0.0.1"
#define DEFAULT_SERVER_PORT1  8888
#define DEFAULT_SERVER_PORT2  9999
int main(int argc, char **argv)
{
    boost::asio::io_context ctx;
    BoostServer server(ctx, DEFAULT_SERVER_PORT1, DEFAULT_SERVER_PORT2, DEFAULT_SERVER_IP, DEFAULT_SERVER_IP);
    ctx.run();
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.0)
project(boostServer VERSION 0.1.0)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
#boost库检查
find_package(Boost 1.77.0 COMPONENTS context thread date_time program_options filesystem system coroutine log_setup log REQUIRED)
if(Boost_FOUND)
  include_directories(${Boost_INCLUDE_DIRS})
  link_directories(${Boost_LIBRARY_DIRS})
else()
  message("check boost lib failed!")
endif()
add_executable(boostServer  main.cpp
  boostServer.h  boostServer.cpp
)
target_link_libraries(${PROJECT_NAME} 
  pthread libboost_thread.a  libboost_filesystem.a libboost_log_setup.a libboost_log.a libboost_locale.a
  libboost_coroutine.a  libboost_context.a
)


推荐一个零声学院免费教程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,点击立即学习:

相关文章
|
11天前
|
弹性计算 开发工具 git
2分钟在阿里云ECS控制台部署个人应用(图文示例)
作为一名程序员,我在部署托管于Github/Gitee的代码到阿里云ECS服务器时,经常遇到繁琐的手动配置问题。近期,阿里云ECS控制台推出了一键构建部署功能,简化了这一过程,支持Gitee和GitHub仓库,自动处理git、docker等安装配置,无需手动登录服务器执行命令,大大提升了部署效率。本文将详细介绍该功能的使用方法和适用场景。
2分钟在阿里云ECS控制台部署个人应用(图文示例)
|
1月前
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
139 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
|
1月前
|
JSON 数据格式 Python
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
本文介绍了如何使用Python的socket模块实现客户端到服务器端的文件传输,包括客户端发送文件信息和内容,服务器端接收并保存文件的完整过程。
149 1
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
|
1月前
使用Netty实现文件传输的HTTP服务器和客户端
本文通过详细的代码示例,展示了如何使用Netty框架实现一个文件传输的HTTP服务器和客户端,包括服务端的文件处理和客户端的文件请求与接收。
43 1
使用Netty实现文件传输的HTTP服务器和客户端
|
1月前
|
网络协议 Unix Linux
一个.NET开源、快速、低延迟的异步套接字服务器和客户端库
一个.NET开源、快速、低延迟的异步套接字服务器和客户端库
|
1月前
|
网络协议 Java API
【网络】TCP回显服务器和客户端的构造,以及相关bug解决方法
【网络】TCP回显服务器和客户端的构造,以及相关bug解决方法
62 2
|
1月前
|
存储 网络协议 Java
【网络】UDP回显服务器和客户端的构造,以及连接流程
【网络】UDP回显服务器和客户端的构造,以及连接流程
52 2
|
1月前
|
安全 区块链 数据库
|
1月前
|
存储 网络协议 Unix
docker的底层原理一:客户端-服务器架构
本文详细解释了Docker的客户端-服务器架构,包括常驻后台的Docker守护进程、通过命令行接口发送请求的Docker客户端、以及它们之间通过Unix socket或网络接口进行的通信。
22 0
|
2月前
|
弹性计算 运维 监控
阿里云ECS实例使用示例
使用阿里云ECS实例的流程简便快捷:登录阿里云控制台,在ECS实例列表中选择目标实例并进入详情页,点击“启动”按钮激活实例,确保预装系统和应用完成。运行后,通过控制台监控CPU、内存及磁盘使用情况,如需调整配置,可选择实例后点击“重启”应用新设置。阿里云ECS助力企业轻松上云、高效运维。[1][3] 相关链接:阿里云ECS使用流程 https://startup.aliyun.com/info/1078898.html
下一篇
无影云桌面