C ++ IRC客户端设计

时间:2015-09-26 08:39:51

标签: c++11 asynchronous boost boost-asio

我正在尝试编写符合RFC 2812标准的C ++ IRC库。 我在设计客户端时遇到了一些麻烦。 根据我的阅读,IRC通信往往是异步的。

我正在使用boost::asio::async_readboost::asio::async_write。 通过阅读我收集的文档,您可以在完成之前执行多个async_write请求。因此,您最终会得到相当嵌套的回调。这不是打败异步调用的目的吗?使用同步调用防止嵌套不是更好吗?如果没有,为什么?

其次,如果我没有弄错的话,每个boost::asio::async_write都应该跟boost::asio::async_read跟进,以接收服务器对发送的命令的响应。因此,我的客户端函数需要接受一个回调参数,以便该类用户可以在客户端收到响应后执行某些操作(例如发送另一条消息...)。

如果我要继续使用异步执行此操作,我应该保留std::deque<std::tuple<message, callback>>并且每次boost::asio::async_write完成,并且队列中有一个元组,出列并发送消息然后提高回调?这是实现这个系统的最佳方式吗?

我一直在思考,因为消息一直被发送,我将不得不实现某种类型的侦听器循环来排队响应,但是如何将这些响应与触发它们的特定命令相关联?或者,如果响应只是来自其他用户的频道消息?

2 个答案:

答案 0 :(得分:2)

IRC协议是全双工协议。因此,应始终监听服务器连接,期望命令处理。可以认为,主要应该使用从服务器接收的消息来更新状态,而不是关联请求和响应,因为服务器可能不响应命令或者可能比预期更晚响应。例如,可以发出WHOIS命令,但在收到对PRIVMSG的响应之前会收到多个WHOIS命令。对于聊天客户端,用户可能希望在等待WHOIS的响应时能够接收聊天消息。因此,拥有async_write()async_read()的调用链在处理协议时可能并不理想。

对于给定的套接字,如果存在未完成的组合读取操作,并且如果存在未完成的组合写入操作,则Asio文档建议不启动其他读取操作。排队消息并从队列中进行异步调用链处理是实现此建议的好方法。考虑使用队列和异步调用链读取此answer以获得一个很好的解决方案。

另外,请注意,即使在活动连接上,服务器也可能发送PING命令。当客户端使用PONG命令进行响应时,可能需要在出站队列的前面插入PONG命令,以便尽快将其发送出去。

答案 1 :(得分:1)

  

这是不是打败了进行异步调用的目的?

通常的解决方案是使用股线:

Why do I need strand per connection when using boost::asio?

您可以使用(隐式)strand¹在同一个io对象上排队多个异步操作。

使用strand确保在相同的逻辑线程上调用完成处理程序。

在协议

在发送下一个命令之前,您确实可以保留命令队列并等待每个命令的响应。

如果您可以通过不同的类型回复来发现相关性,那么您可能会更聪明一些,但是您需要按类型保留队列命令我认为过早优化。