C++ 基于套接字的事件循环
我想设置基于套接字的服务器-客户端通信。客户端可以连接到服务器并从中接收不同的通知。这可以在客户端实现,如下所示C++ 基于套接字的事件循环,c++,sockets,unix,event-loop,C++,Sockets,Unix,Event Loop,我想设置基于套接字的服务器-客户端通信。客户端可以连接到服务器并从中接收不同的通知。这可以在客户端实现,如下所示 ... Message* msg = NULL; while ( msg = receiveMessage() ) handleMessage( msg ); ... 此代码将在客户端的独立线程中运行,并应处理来自服务器的不同类型的通知。但客户端也应该能够通过发送请求与套接字通信,即 Request requestMsg; if ( sendMessage( request
...
Message* msg = NULL;
while ( msg = receiveMessage() )
handleMessage( msg );
...
此代码将在客户端的独立线程中运行,并应处理来自服务器的不同类型的通知。但客户端也应该能够通过发送请求与套接字通信,即
Request requestMsg;
if ( sendMessage( requestMsg ) )
{
Message* response = receiveMessage();
if ( response->type() == REQUEST_REPLY )
...
}
问题:如何实现这一点?我不想中断阅读线程,但我应该收到对特定请求的响应。这是基于本地域流的unix套接字。..::下面是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.
…::下面的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 < /C>。下面是一个线程安全对象的简单实现,它可能适合您的需要
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;
class消息队列
{
公众:
typedef std::共享的\u ptr SpMessage;
bool empty()常量{
std::锁\保护锁(互斥锁);
返回消息_u3;.empty();
}
SpMessage pop(){
std::锁\保护锁(互斥锁);
SpMessage msg(messages_u.front());
消息u.pop_front();
返回味精;
}
无效推送(SpMessage const&msg)
std::锁\保护锁(互斥锁);
消息推回(msg);
}
私人:
MessageQueue(const MessageQueue&);//使残废
MessageQueue&运算符=(const MessageQueue&);//使残废
std::向量消息;
std::mutex mutex;
};
typedef std::shared_ptr SpMessageQueue;
此时,您有了一个可共享的线程安全队列。在主线程和套接字线程之间共享此队列。如果希望发送也在单独的线程上,也可以使用两个线程,例如,从一个消息队列弹出消息,处理它,并在另一个队列上排队响应
您可以在服务器上使用同样的东西
message类应该能够存储一个std::vector
,这样您就可以通过套接字发送/接收普通的旧数据,并将其装入和取出消息进行处理
如果您需要有关启动线程的帮助,请查看本教程 在客户端的接收方线程中,应该使用线程安全对象来推送和弹出消息。如果你有一个C++ 11编译器,你可以考虑<代码> STD::vector < /C>。下面是一个线程安全对象的简单实现,它可能适合您的需要
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;
class消息队列
{
公众:
typedef std::共享的\u ptr SpMessage;
bool empty()常量{
std::锁\保护锁(互斥锁);
返回消息_u3;.empty();
}
SpMessage pop(){
std::锁\保护锁(互斥锁);
SpMessage msg(messages_u.front());
消息u.pop_front();
返回味精;
}
无效推送(SpMessage const&msg)
std::锁\保护锁(互斥锁);
消息推回(msg);
}
私人:
MessageQueue(const MessageQueue&);//使残废
MessageQueue&运算符=(const MessageQueue&);//使残废
std::向量消息;
std::mutex mutex;
};
typedef std::sharedptr SpMessageQueue;
此时,您有了一个可共享的线程安全队列。在主线程和套接字线程之间共享此队列。如果希望发送也在单独的线程上,也可以使用两个线程,例如,从一个消息队列弹出消息,处理它,并在另一个队列上排队响应
您可以在服务器上使用同样的东西
message类应该能够存储一个std::vector
,这样您就可以通过套接字发送/接收普通的旧数据,并将其装入和取出消息进行处理
如果您需要有关启动线程的帮助,请查看本教程 是否可以提供使用此MessageQueue类的完整示例?是否可以提供使用此MessageQueue类的完整示例?