【发布时间】:2012-02-14 01:20:19
【问题描述】:
好吧,我实际上还没有代码,因为我暂时只是在挑选一个框架,但我仍然对我希望如何去做这件事感到有点困惑:.
服务器端,我希望有一个类,其中每个实例都有一个套接字和标识每个连接的各种信息。每个对象都有自己的线程来接收数据。我知道我将如何实现其中的大部分内容,但是当我开始在服务器和客户端之间实际传输数据时,我的困惑就开始了。对于特定情况,我想要一堆不同的消息结构(例如 CONNECT_MSG 、 DISCONNECT_MSG 、 POSTTEXT_MSG 等),然后我所要做的就是在该结构上有一个 char * 点,然后通过发送传递它() 函数。
但正如我所想的那样,在这一点上它变得有点复杂。可以发送任何这些不同的消息类型,并且在接收端,您将不知道应该将传入缓冲区转换为什么。我希望做的是,在每个连接对象的线程中,让它阻塞,直到它接收到带有消息的数据包,然后将其转储到由服务器管理的单个队列对象(互斥锁将防止贪婪),然后是服务器将独立于连接对象以 FIFO 顺序处理每条消息。
我还没有写任何东西,但让我写一些东西来说明我的设置。
#define CONNECT 1000
struct GENERIC_MESSAGE
{
int id;
}
struct CONNECT_MESSAGE : public GENERIC_MESSAGE
{
m_username;
}
void Connection::Thread()
{
while(1)
{
char buffer[MAX_BUFFER_SIZE]; // some constant(probably 2048)
recv(m_socket, buffer, MAX_BUFFER_SIZE, 0);
MESSAGE_GENERIC * msg = reinterpret_cast<MESSAGE_GENERIC *> (buffer);
server->queueMessage(msg);
}
}
void Server::QueueMessage(MESSAGE_GENERIC * msg)
{
messageQueue.push(msg);
}
void Server::Thread()
{
while(1)
{
if(!messageQueue.empty())
ProcessMessages();
else
Sleep(1);
}
}
void Server::ProcessMessages()
{
for(int i = 0; i < messageQueue.size(); i++)
{
switch(messageQueue.front()->id)
{
case CONNECT:
{
// the part i REALLY don't like
CONNECT_MESSAGE * msg = static_cast<CONNECT_MESSAGE *>(messageQueue.front() );
// do the rest of the processing on connect
break;
}
// other cases for the other message types
}
messageQueue.pop();
}
}
如果您一直跟进到现在,您就会意识到这是多么愚蠢和脆弱。它转换为基类,将该指针传递给队列,然后假设该指针在另一个线程中仍然有效,即使这样,派生类的其余部分的指针之后的剩余缓冲区是否总是之后对铸造有效,但我还没有找到正确的方法。我愿意接受任何建议,无论是使这项工作发挥作用,还是完全不同的消息传递设计。
【问题讨论】:
标签: c++ visual-c++ winsock2