C++ C++;Boost Assio-在另一个线程中启动

C++ C++;Boost Assio-在另一个线程中启动,c++,boost,C++,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:

我在我的项目中推动了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
服务器.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_;
    };
}
\ifndef VIBRANIUM\u CORE\u SERVER\u H
#定义VIBRANIUM_CORE_SERVER_H
#包括
#包括
#包括
#包括
#包括
使用boost::asio::ip::tcp;
弧菌{
类服务器{
公众:
服务器(boost::asio::io_上下文和io_上下文,短端口)
:接受器(io_上下文,tcp::端点(tcp::v4(),端口))
{
你接受吗;
}
私人:
无效不接受();
tcp::接受者接受者;
};
}
Server.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();
    });
}
#包括“Server.h”
#包括“Session.h”
使用振动筛;
无效服务器::do_accept(){
接受器异步接受器([this](boost::system::error\u code ec,tcp::socket)
{
如果(!ec)
{
std::make_shared(std::move(socket))->start();
}
你接受吗;
});
}
下面是我如何启动服务器:

#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;
}
#包括“Config.h”
#包括“Database/MySQLConnection.h”
#包括“实施/登录数据库.h”
#包括“Banner.h”
#包括“Server/Server.h”
#包括
使用boost::asio::ip::tcp;
使用名称空间std;
使用振动筛;
int main(){
//别介意Logger::FatalError它只是用来着色的!
横幅::显示(记录器::错误,“AuthServer”);
配置(“AuthServer”);
MySQLConnectionInfo MySQLConnectionInfo(配置,“登录数据库信息”);
登录数据连接登录数据连接(mySqlConnectionInfo);
loginDatabaseConnection.LoadDatabase();
尝试
{
boost::asio::io_上下文io_上下文;
服务器s(io_上下文,8080);
io_context.run();
}
捕获(标准::异常&e)
{
标准:cerr
1.当我启动服务器时,我看不到“服务器已启动!”的消息。我怀疑这是因为它阻止了我当前的线程。我该如何启动
在另一个线程中启动TCP服务器?它应该在单独的线程中吗
线还是线

只要有任何正在进行的任务,io_context.run()就会被阻止。您需要在io_context.run()之前调用“服务器已启动”,可能在服务器构造函数中

2.我实现的示例只是返回发送到服务器的内容。您能提供一些示例,说明如何区分不同的内容吗 事件消息?我想要实现的是当我发送 以0x001开头的消息,指出这是针对的聊天消息 示例或当消息以0x002开始时,我的服务器会知道 客户正在通知某人已注销

有很多方法可以做到这一点,但对于ex,您可以只设置一个消息字段来携带此信息

3.我认为Boost Assio使用的是TCP上的二进制协议,对吗

在您的情况下,是的,因为您使用的是boost::asio::ip::tcp,但不是必需的。还有boost::asio::ip::udp用于udp支持

4.您能告诉我如何使用二进制协议通过TCP发送结构吗

您可以只为您的结构实现boost序列化方法 模板 void序列化(存档&ar,常量unsigned int版本)。 查看或提供您自己的序列化(从示例到文本)并发送这些数据

如果实现boost序列化,则可以将结构直接传递给asio函数,否则必须发送序列化的字节


很抱歉,我没有时间为您编写整个代码。

谢谢您的详细回答。这里:他们说
async\u write
将自动为我序列化数据。因此,在这种情况下,我不需要为序列化而烦恼,对吗?另外,如果我从服务器发送结构A{},我应该具有完全相同的结构A{}在客户端,我是对的吗?是的,但是这里隐式地使用了boost序列化库(通过在void serialize(Archive&ar,const unsigned int version in stock.hpp)中提供序列化函数).boost序列化中的&运算符同时执行两项操作:序列化/反序列化,具体取决于输入流还是输出流。@VenelinVasilev在该示例中,
连接
对象通过boost.serialization提供序列化,但这不是Asio的一部分;它是.Asio,仅处理传输层协议(即TCP、UDP);您可以在所选传输协议的基础上实现任何您想要的应用层协议。谢谢@StPiere。您可以给出如何形成和读取头数据包以及头数据包正文的示例吗?在我的示例中也是@StPiere。TCP服务器是异步的,对吗?这意味着它可以在sa中并行执行许多任务给我时间?
#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;
}
std::cout << "Server Started!" << std::endl;
io_context.run();