我想基于套接字设置服务器 - 客户端通信。客户端可以连接到服务器并从中接收不同的通知。这可以在客户端实现,如下所示
...
Message* msg = NULL;
while ( msg = receiveMessage() )
handleMessage( msg );
...
此代码将在客户端的独立线程中运行,并应处理来自服务器的不同类型的通知。但客户端也应该能够通过发送请求与套接字进行通信,即
Request requestMsg;
if ( sendMessage( requestMsg ) )
{
Message* response = receiveMessage();
if ( response->type() == REQUEST_REPLY )
...
}
问题:如何实现这一目标?我不想中断读取线程,但我应该收到对特定请求的响应。这是基于本地域流的unix套接字。
答案 0 :(得分:1)
... :::下面的ASCII东西::: ...
如果你讨厌艺术,或者ASCII停在这里。
下方的示意图将不会阻止服务器或客户端。
许多MMORPGS使用它来保护连接并使协议更难破解。
[================ ~~ 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.
答案 1 :(得分:1)
在客户端的接收器线程中,您应该使用线程安全对象来推送和弹出消息。如果您可以访问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>
,以便您可以通过套接字发送/接收普通旧数据,然后填充Message
以进行处理。
如果您在启动线程时需要帮助,请查看本教程。 http://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/