[英]C++ Boost Assio - Start in another thread
我的项目中有 Boost Assio 实现。 这里是:
会话.h:
#ifndef VIBRANIUM_CORE_SESSION_H
#define VIBRANIUM_CORE_SESSION_H
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
namespace Vibranium{
class Session
: public std::enable_shared_from_this<Session>
{
public:
Session(tcp::socket socket)
: socket_(std::move(socket))
{
}
void start();
private:
void do_read();
void do_write(std::size_t length);
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
}
#endif //VIBRANIUM_CORE_SESSION_H
会话.cpp:
#include "Session.h"
void Vibranium::Session::start() {
do_read();
}
void Vibranium::Session::do_read() {
auto self(shared_from_this());
socket_.async_read_some(boost::asio::buffer(data_, max_length),
[this, self](boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
do_write(length);
}
});
}
void Vibranium::Session::do_write(std::size_t length) {
auto self(shared_from_this());
boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
do_read();
}
});
}
服务器.h:
#ifndef VIBRANIUM_CORE_SERVER_H
#define VIBRANIUM_CORE_SERVER_H
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
namespace Vibranium{
class Server {
public:
Server(boost::asio::io_context& io_context, short port)
: acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
{
do_accept();
}
private:
void do_accept();
tcp::acceptor acceptor_;
};
}
服务器.cpp:
#include "Server.h"
#include "Session.h"
using namespace Vibranium;
void Server::do_accept() {
acceptor_.async_accept([this](boost::system::error_code ec, tcp::socket socket)
{
if (!ec)
{
std::make_shared<Session>(std::move(socket))->start();
}
do_accept();
});
}
这是我启动服务器的方式:
#include "Config.h"
#include "Database/MySQLConnection.h"
#include "Implementation/LoginDatabase.h"
#include "Banner.h"
#include "Server/Server.h"
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
using namespace std;
using namespace Vibranium;
int main() {
//Don't mind Logger::FatalError it's just for coloring!
Banner::Show(Logger::Error,"AuthServer");
Config config("AuthServer");
MySQLConnectionInfo mySqlConnectionInfo(config, "LoginDatabaseInfo");
LoginDatabaseConnection loginDatabaseConnection(mySqlConnectionInfo);
loginDatabaseConnection.LoadDatabase();
try
{
boost::asio::io_context io_context;
Server s(io_context, 8080);
io_context.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
std::cout << "Server Started!" << std::endl;
return 0;
}
我有几个问题:
如果问题太多,请只考虑问题 1。
1.当我启动服务器时,我看不到消息“服务器启动!”。 我怀疑这是因为它阻塞了我当前的线程。 如何在另一个线程中启动 TCP 服务器? 它应该在单独的线程中还是?
std::cout << "Server Started!" << std::endl;
之后被调用
io_context.run();
只要有任何正在进行的任务,io_context.run() 就会阻塞。 您需要在 io_context.run() 之前调用“Server Started”,可能在 Server 构造函数中
2.我实现的例子只是返回发送到服务器的内容。 您能否建议我如何区分不同事件消息的任何示例? 我想要实现的是,当我发送以 0x001 开头的消息以指出这是聊天消息时,或者当消息以 0x002 开头时,我的服务器知道客户端正在通知某人已注销。
有很多方法可以做到这一点,但例如。 您可以只设置消息的一个字段来携带此信息。
3.我认为 Boost Assio 使用的是基于 TCP 的二进制协议。 我对吗?
在您的情况下,是的,因为您使用的是 boost::asio::ip::tcp,但不是必需的。 还有 boost::asio::ip::udp 用于 udp 支持。
4.你能告诉我如何使用二进制协议通过 TCP 发送结构吗?
您可以为结构模板 void serialize(Archive& ar, const unsigned int version)实现 boost 序列化方法。 请参阅提升示例。 或提供您自己的序列化(例如文本)并发送这些数据。
如果你实现了 boost 序列化,那么你可以将你的结构直接传递给 asio 函数,否则你必须发送序列化的字节。
抱歉,没有时间为您编写整个代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.