基于套接字的事件循环
Socket based event loop
我想设置基于套接字的服务器-客户端通信。客户端可以连接到服务器并从中接收不同的通知。这可以在客户端实现,如下
...
Message* msg = NULL;
while ( msg = receiveMessage() )
handleMessage( msg );
...
此代码将在客户端的独立线程中运行,并且应该处理来自服务器的不同类型的通知。但是客户端也应该能够通过发送请求与套接字通信,即
Request requestMsg;
if ( sendMessage( requestMsg ) )
{
Message* response = receiveMessage();
if ( response->type() == REQUEST_REPLY )
...
}
问题:如何实现这一点?我不想中断读取线程,但我应该收到对特定请求的响应。这是基于本地域流的unix套接字。
…::ASCII内容如下::。。。
如果你讨厌艺术,或者ASCII,就到此为止。
下面的示意图不会阻塞服务器和客户端
许多MMORPG都使用它来保护连接,并使协议更难破解。
[================ ~~ Server ~~ ================]
[ Select / Poll ]*4 5*[ Dispatcher ]
|| / ||
|| || ||
*1 || ||2* *3||
|| || ||
/ || /
[ Thread 1 Basic IO ] [ Thread 2 Listener]
[=============== ~~ Client ~~ =================]
*1 // send
*2 // recv
*3 // bind listen accept recv OR they will communicate using UDP
// to a different port
*4 // the server will process the clients normally
// using select / poll / epoll / kqueue / `/dev/poll`
*5 // The client will either setup a temporary server to process
// the servers opcodes
OR
// It will accept UDP packets using recvfrom()
*5 // I'd recommend using UDP so that the server can loop through the existing
// connections and sendto() the opcodes which will be provided via a message
// queue.
在客户端的接收器线程中,应该使用线程安全对象来推送和弹出消息。如果您有权访问C++11编译器,您可以考虑使用std::vector<std::shared_ptr<Messsage>>
。下面是一个线程安全对象的简单实现,它可能适合您的需要。
class MessageQueue
{
public:
typedef std::shared_ptr<Message> SpMessage;
bool empty() const {
std::lock_guard<std::mutex> lock(mutex_);
return messages_.empty();
}
SpMessage pop() {
std::lock_guard<std::mutex> lock(mutex_);
SpMessage msg(messages_.front());
messages_.pop_front();
return msg;
}
void push(SpMessage const& msg)
std::lock_guard<std::mutex> lock(mutex_);
messages_.push_back(msg);
}
private:
MessageQueue(const MessageQueue&); // disable
MessageQueue& operator=(const MessageQueue&); // disable
std::vector<SpMessage> messages_;
std::mutex mutex_;
};
typedef std::shared_ptr<MessageQueue> SpMessageQueue;
此时,您有了一个可共享的线程安全队列。在主线程和套接字线程之间共享此队列。如果您希望发送也在一个单独的线程上,也可以使用两个,例如,从一个消息队列弹出,处理它,并在另一个队列上排队响应。
你可以在你的服务器上使用同样的东西。
消息类应该能够存储一个std::vector<char>
,这样您就可以通过套接字发送/recv普通的旧数据,并将其放入和取出Message
进行处理。
如果您需要有关启动线程的帮助,请查看本教程。http://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/
相关文章:
- 具有Qt事件循环的可移植通用共享库设置
- 如何将事件循环中的事件分派给订阅者?
- C++uWebSockets将事件循环集成到一个线程中
- 了解如何在不冻结事件循环的情况下在 QThread 中休眠/等待
- 如何在主事件循环之前创建一些对象?
- Libuv:保护事件循环免受并发访问
- 防止模式对话框中的事件循环阻塞
- QCoreApplication事件循环和Windows服务控制处理程序功能
- c++ 过期映射条目线程与事件循环
- Qt的事件循环线程是安全的还是原子的?处理"队列连接"时如何同步?
- 在事件循环启动后删除并创建新的 RTP 流
- QSTATEMACHINE事件循环与动画
- 等待事件循环为空 /等到QT5小部件关闭
- 如何将lambda函数排队到Qt的事件循环中?
- DLL中的QT事件循环
- 运行Qt 5.10事件循环howto的Windows服务service_WIN32_OWN_PROCESS
- 模态qprogressdialog :: setValue()导致嵌套事件循环崩溃
- 什么是QT中的事件循环
- Libuv中SD-BUS的事件循环处理
- Qt的事件循环是FIFO吗?