您在 Boost.Asio 文档中提到的示例实际上非常适合了解事情是如何工作的。您是对的,起初它可能看起来有点难以理解,特别是如果您不熟悉这些概念。但是,我建议您从聊天服务器示例开始,并在您的计算机上构建它。这将使您能够更仔细地观察事物并开始改变事物以了解它是如何工作的。让我指导您完成一些我认为对入门很重要的事情。
根据您的描述,您想做什么,似乎聊天服务器为您提供了一个很好的起点,因为它已经有您需要的类似部分。让服务器异步是你想要的,因为你可以很容易地用一个线程处理多个客户端。从一开始就没有什么太复杂的事情。
在这种情况下,简化的异步意味着您的服务器处理队列,获取处理程序(任务)并执行它。如果队列中没有任何内容,则它只是等待将某些内容放入队列中。在您的情况下,这意味着它可能是来自客户端的连接、来自客户端的新消息读取或类似的东西。为了使其工作,需要设置每个处理程序(处理对特定事件的反应的函数)。
让我用聊天服务器示例中的代码解释一下。
在server source file 中,您会看到chat_server 类在构造函数中调用start_accept。在这里接受处理程序被设置。
void start_accept()
{
chat_session_ptr new_session(new chat_session(io_service_, room_)); // 1
acceptor_.async_accept(new_session->socket(), // 2
boost::bind(&chat_server::handle_accept, this, new_session, // 3
boost::asio::placeholders::error)); // 4
}
第 1 行:创建了一个 chat_session 对象,它表示一个客户端和服务器之间的会话。为接受创建一个会话(还没有客户端连接)。
第 2 行:套接字的异步接受...
第 3 行:......当它发生时,一定要调用 chat_server::handle_accept。会话被传递给第一个连接的客户端使用。
现在,如果我们查看handle_accept,我们会看到在客户端连接时,会为会话调用start(这只是在服务器和客户端之间启动东西)。最后,如果其他客户端也想连接,则将新的接受置于未完成状态。
void handle_accept(chat_session_ptr session,
const boost::system::error_code& error)
{
if (!error)
{
session->start();
}
start_accept();
}
这也是你想要的。对传入连接的出色接受。如果多个客户端可以连接,则应该始终有一个未完成的,以便服务器可以处理接受。
服务器和客户端如何交互都在会话中,您可以遵循相同的设计并对其进行修改以做您想做的事情。您提到服务器需要查看发送的内容并执行不同的操作。看看chat_session 和start 被服务器调用的handle_accept 函数。
void start()
{
room_.join(shared_from_this());
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.data(), chat_message::header_length),
boost::bind(
&chat_session::handle_read_header, shared_from_this(),
boost::asio::placeholders::error));
}
这里重要的是调用boost::asio::async_read。这也是你想要的。这会在套接字上进行未完成的读取,因此服务器可以读取客户端发送的内容。有一个处理程序(函数)绑定到此事件chat_session::handle_read_header。每当服务器读取套接字上的某些内容时,都会调用它。在这个处理函数中,您可以开始放置您的特定代码来确定如果发送特定消息时要执行的操作等等。
重要的是要知道,每当调用这些异步 boost::asio 函数时,该调用中都不会发生任何事情(即,如果调用 read 函数,则不会读取套接字)。这是异步方面。您只需为某事注册一个处理程序,然后在发生这种情况时回调您的代码。因此,当调用此读取时,它将立即返回,并且您将返回服务器的handle_accept(如果您遵循调用方式)。如果您还记得那里,我们还调用start_accept 来设置另一个异步接受。此时,您有两个未完成的处理程序等待另一个客户端连接或第一个客户端发送内容。根据首先发生的情况,将调用特定的处理程序。
另外重要的是要了解,无论何时运行某事,它都会不间断地运行,直到它需要做的所有事情都完成为止。即使有触发它们的未完成事件,其他处理程序也必须等待。
最后,为了运行服务器,您需要 io_service,这是 Asio 的核心概念。
io_service.run();
这是您在main 函数中看到的一行。这只是说线程(示例中只有一个)应该运行 io_service,它是当有工作要做时处理程序进入队列的队列。当什么都没有时,io_service 只是等待(当然在那里阻塞主线程)。
我希望这可以帮助您开始您想做的事情。你可以做很多事情,也有很多事情要学习。我觉得它是一个很棒的软件!祝你好运!