多线程服务器设计
Multithread server design
我目前正在编写一个游戏服务器。我使用boost::asio与io_service。我遇到了一个会话类超出范围的问题(我不确定何时安全地删除它),并向多个客户端发送数据包。这是我当前的代码
class io_pool
{
void Run(int threads)
{
// make as much threads as user wants + call io_service.run from all threads
// so I have one io_service, which consumes more than 1 thrread
}
}
// the server that accepts
class server
{
void Accept()
{
// create new session and wait for session to connect
}
void OnAccept()
{
// call session start, and call accept again to wait for more
}
}
// a connection from a client
class session
{
// keep track of a client
// holds SendPacket, RecvPacket and stuff like that
// here is no problem with multithread since the callback frmo a socket can't be called at the same time
}
// the basic class
class client
{
// holds info about character, map etcetc
// has also a SendPacket() function which calls the session one.
}
// keeps track of all players in maps
class world_server
{
std::map<dword /* map id*/, std::vector<std::shared_ptr<client>>>; // to hold info about the players in a map
void AddPlayer(dword map id, client);
void RemovePlayer(dword map id, client);
std::vector<std::shared_ptr<client>>& GetPlayersdword (map_id);
}
在Io_service池中,我创建了一个Io_service,并在整个程序中传递。
当用户或I关闭套接字时问题开始。boost中的read_async()函数调用回调函数时会出现如下错误代码:
void Session::Stop()
{
m_socket.shutdown(boost::asio::socket_base::shutdown_both);
m_socket.close();
m_time_out.Stop();
// call here the delete function in tcp_server class?
}
if (e || bytes_transferred != 4)
{
if (e == boost::asio::error::operation_aborted)
return;
Stop();
return;
}
但是当我调用socket.close/shutdown()时,有时错误代码不是operation_aborted。这在我的Stop()函数中给出了一个错误,因为我在调用delete函数(调用服务器DeleteClient())时两次中止同一个套接字,我得到了访问冲突,导致类超出了作用域。
这也带来了我的下一个问题,当另一个会话,正在更新自己的运动,并希望将信息发送到同一地图中的所有其他会话时,会发生什么。我用客户机调用io_service.post()。SendPacket作为信息。但是,如果在此之前删除了会话,则不会以与上面相同的错误结束。
我想出了一个丑陋的解决方案是在30秒后用计时器删除会话类。因为我猜没有一个处理程序需要30秒才能被调用,所以这应该是可行的。虽然在我看来很丑。
谢谢你的阅读,我很欣赏任何对设计的批评
Gr
听起来您可以通过添加一些状态标志和测试来解决大部分或所有这些问题。当你有一些停止或关闭服务的操作时,设置状态标志,例如:
HasBeenShutDown = true;
当你要做一些依赖于服务未被关闭(包括关闭它)的事情时,测试标志,例如:
if (HasBeenShutDown) return;//或者DoAppropriateCleanup();
但更大的问题将是理解在这些情况下需要发生什么,而不仅仅是避免崩溃。当你的部分系统已经关闭,但你想要恢复并继续运行,需要发生什么才能再次回到有序的工作状态,而不会打乱你的游戏状态。
- C/C++ Linux 上的多线程服务器/客户端崩溃
- 设计低线程争用的多线程聊天服务器
- 使用线程池提升 ASIO 多线程 TCP 服务器
- C++多线程服务器
- 简单的非阻塞多线程 tcp 服务器
- 多线程套接字编程服务器仅从 1 个客户端线程获取消息
- 来自 boost 的 udp 服务器不适用于多线程,但仅在主线程上工作
- 在C 中将多个客户端连接到Windows中的单个服务器中的多线程
- 多线程客户端/服务器原型中的分割故障
- 在多线程HTTP服务器中发送后,如何干净地关闭套接字
- 卫生多线程服务器
- C 多线程TCP服务器问题
- gSOAP C++ 多线程独立服务器和客户端示例
- C++中的多线程 Web 服务器
- 在多线程c++服务器应用程序中处理非常量全局配置
- 多线程服务器在一个线程中处理多个客户端
- 带有libevent的多线程HTTP服务器
- c++tcp多线程客户端/服务器-如何与线程套接字处理程序进行通信
- 如何使我的服务器多线程
- 服务器多线程无法保存最后一个套接字描述符