基础示例,根据客户端发送的消息,再原样返回
main.cpp
#include <iostream>
#include<boost/asio.hpp>
#include"Server.h"
int main()
{
boost::asio::io_context ioc;
boost::asio::io_context ioc2;
Server server(ioc,12345);
std::cout<<"Server started"<<std::endl;
while (1);
return 0;
}
Session.h
#pragma once
#include<boost/asio.hpp>
#include<queue>
#include<mutex>
class Server;
#include"Server.h"
// 会话类,继承自enable_shared_from_this以支持在回调函数中使用shared_ptr
class Session : public std::enable_shared_from_this<Session>
{
public:
// 构造函数,初始化会话对象
Session(boost::asio::io_context& ioc, Server* server);
// 获取会话的socket对象引用
boost::asio::ip::tcp::socket& getSocket();
// 启动会话处理
void start();
// 发送消息
void sendMess(boost::asio::const_buffer msg, std::shared_ptr<Session> self);
// 处理发送操作完成后的回调
void handleSend(const boost::system::error_code ec, std::size_t bytes_transferred, std::shared_ptr<Session> self);
// 读取数据
void read(boost::system::error_code ec, std::size_t bytes_transferred, std::shared_ptr<Session> self);
// 析构函数
~Session();
private:
// 会话的socket对象
boost::asio::ip::tcp::socket sock;
// 待发送消息队列
std::queue<boost::asio::const_buffer> quebuf;
// 读取数据的缓冲区
char read_buffer[1024] = { 0 };
// 缓冲区中数据长度
int l = 0;
// 发送操作互斥锁
std::mutex send_mutex;
// 关联的服务器对象指针
Server* server;
};
Session.cpp
#include "Session.h"
#include<iostream>
Session::Session(boost::asio::io_context& ioc, Server* server):sock(ioc),server(server)
{
}
boost::asio::ip::tcp::socket& Session::getSocket()
{
return sock;
}
void Session::start()
{
sock.async_read_some(boost::asio::buffer(read_buffer, 1024),
std::bind(&Session::read, this, std::placeholders::_1, std::placeholders::_2,shared_from_this()));
}
void Session::sendMess(boost::asio::const_buffer msg, std::shared_ptr<Session> self)
{
std::lock_guard<std::mutex> lock(send_mutex);
if (!quebuf.empty())
{
quebuf.push(msg);
}
else
{
quebuf.push(msg);
sock.async_send(quebuf.front(), std::bind(&Session::handleSend, this, std::placeholders::_1, std::placeholders::_2,self));
}
}
void Session::handleSend(const boost::system::error_code ec, std::size_t bytes_transferred, std::shared_ptr<Session> self)
{
if (ec)
{
std::cout << ec.value() << " - " << ec.message();
server->stopSession(shared_from_this());
}
else
{
std::lock_guard<std::mutex> lock(send_mutex);
quebuf.pop();
if (!quebuf.empty())
{
sock.async_send(quebuf.front(), std::bind(&Session::handleSend, this, std::placeholders::_1, std::placeholders::_2,self));
}
}
}
void Session::read(boost::system::error_code ec, std::size_t bytes_transferred, std::shared_ptr<Session> self)
{
if (ec)
{
std::cout << ec.value() << " = " << ec.message() << std::endl;
server->stopSession(shared_from_this());
}
else
{
std::cout << read_buffer + l << std::endl;
sendMess(boost::asio::buffer(read_buffer+l, bytes_transferred),self);
l += bytes_transferred;
sock.async_read_some(boost::asio::buffer(read_buffer + l, 1024 - l), std::bind(&Session::read, this, std::placeholders::_1, std::placeholders::_2,self));
}
}
Session::~Session()
{
std::cout << "Session closed" << std::endl;
}
Server.h
#pragma once
#include<boost/asio.hpp>
#include<set>
class Session;
#include"Session.h"
#include<memory>
class Server
{
public:
// 构造函数,初始化 Server 对象
Server(boost::asio::io_context& io_con, int port);
// 开始接受连接请求
void start();
// 处理连接请求的回调函数
void handle_accept(const boost::system::error_code ec, std::shared_ptr<Session> session_ptr);
// 停止特定会话
void stopSession(std::shared_ptr<Session> session_ptr);
private:
boost::asio::io_context& _ioc; // boost asio io 上下文的引用
int port; // 服务端口号
boost::asio::ip::tcp::acceptor acc; // 接受器对象
std::set<std::shared_ptr<Session>> sessions; // 会话集合
};
Server.cpp
#include"Server.h"
#include<iostream>
Server::Server(boost::asio::io_context& ioc, int port) :_ioc(ioc), port(port),acc(ioc,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),port))
{
start();
ioc.run();
}
void Server::start()
{
std::shared_ptr<Session> session_ptr = std::make_shared<Session>(_ioc,this);
sessions.insert(session_ptr);
acc.async_accept(session_ptr->getSocket(), std::bind(&Server::handle_accept,this, std::placeholders::_1, session_ptr ));
}
void Server::handle_accept( const boost::system::error_code ec, std::shared_ptr<Session> session_ptr )
{
session_ptr->start();
this->start();
}
void Server::stopSession(std::shared_ptr<Session> session_ptr)
{
sessions.erase(session_ptr);
}