多线程服务器设计

时间:2014-06-15 21:02:59

标签: c++ sockets session boost

我目前正在编写游戏服务器。我在io_service中使用boost :: asio。我遇到的问题是会话类超出范围(我不确定何时安全地删除它)并将数据包发送给多个客户端。这是我目前的代码

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。

当用户关闭套接字时,问题就开始了。 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())时,我中止同一个套接字两次+我得到访问冲突,导致类超出范围。

这也带来了我的下一个问题,当另一个会话正在更新自身的移动并希望将信息发送到同一个地图中的所有其他会话时会发生什么。我用client.SendPacket作为信息调用io_service.post()。但是如果届时删除了会话,那么就不会有与上述相同的错误。

我提出的丑陋解决方案是使用计时器在30秒后删除会话类。因为我猜没有一个处理程序需要30秒才能被调用,所以这应该可行。虽然看起来很难看。

感谢阅读,我赞成任何关于设计的所有cirtism

的Gr

1 个答案:

答案 0 :(得分:0)

听起来你可以通过添加一些状态标志和测试来解决大部分或全部问题。只要您有某些操作停止或关闭服务,请设置状态标志,例如:

HasBeenShutDown = true;

无论何时你要做的事情取决于服务没有被关闭(包括关闭它),测试标志,例如:

if(HasBeenShutDown)返回; //或DoAppropriateCleanup();

但更大的问题将是了解除了不崩溃之外的情况需要发生什么。当你的系统部分关闭但你想恢复并继续运行时,需要再次回到有序的工作状态,而不会弄乱你的游戏状态。