繁体   English   中英

C++ Boost Assio - 从另一个线程开始

[英]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. 当我启动服务器时,我看不到消息“服务器已启动!”。 我怀疑这是因为它阻塞了我当前的线程。 如何在另一个线程中启动 TCP 服务器? 它应该在单独的线程中还是?
  2. 我实现的示例只是返回发送到服务器的内容。 您能否建议我如何区分不同事件消息的任何示例? 我想要实现的是,当我发送以 0x001 开头的消息以指出这是聊天消息时,或者当消息以 0x002 开头时,我的服务器知道客户端正在通知某人已注销。
  3. 我认为 Boost Assio 正在使用 TCP 上的二进制协议。 我对吗?
  4. 你能告诉我如何使用二进制协议通过 TCP 发送结构吗?

如果问题太多,请只考虑问题 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM