0

我正在设计一个具有脚本功能的游戏服务器。一般的设计是这样的:

Client connects to Server,
Server initializes Client,
Server sends Client to EventManager (separate thread, uses libevent),
EventManager receives receive Event from Client socket,
Client manages what it received via callbacks.

现在最后一部分对我来说是最棘手的。

目前,我的设计允许我使用一个继承Client来创建对特定接收事件的回调的类。这些回调在一个列表中进行管理,每次接收到某些内容时,接收到的缓冲区都会经过一个解析过程。如果缓冲区有效,则调用回调函数,它作用于缓冲区中的内容。需要注意的一件事是回调可以传递到脚本引擎,此时无法确定会发生什么。

每次回调完成时,都必须重置当前接收缓冲区等。回调当前没有返回值的能力,因为如前所述,任何事情都可能发生。

发生的情况是,当回调中的某处说 this->disconnect() 时,我想立即断开连接Client,将其从 中删除EventManager,最后从 中删除Server,它也应该最终被破坏并释放内存。但是,在客户端中回调完成后,我仍然有一些代码在运行,因此我无法释放内存。

我应该在设计中改变什么?我应该在Server哪些检查哪些Clients 可以自由销毁中进行一些定时事件吗?这会产生我不需要的额外开销吗?回调完成后在堆栈(return -1;)上运行最少的代码是否仍然可以?

我不知道该怎么做,但我愿意接受全面的设计改造。

提前致谢。

4

3 回答 3

1

您可以使用引用计数指针boost::shared_ptr<>来简化内存管理。如果管理器的客户端列表使用shared_ptrs 并且调用回调的代码创建了调用回调的本地副本,则shared_ptr该对象将保持活动状态,直到它从管理器中移除并且回调函数完成:

class EventManager {
  std::vector< boost::shared_ptr<Client> > clients;

  void handle_event(Event &event) {
    // local |handler| pointer keeps object alive until end of function, even
    // if it removes itselfe from |clients|
    boost::shared_ptr<Client> handler = ...;
    handler->process(event);
  }
};

class Client {
  void process(Event &event) {
    manager->disconnect(this);
    // the caller still holds a reference, so the object lives on
  }
}

一旦最后一个对象超出范围,该Client对象将自动被删除,但之前不会。shared_ptr因此,在函数调用之前创建一个本地副本shared_ptr可以确保对象不会被意外删除。

于 2009-09-21T14:05:47.840 回答
1

您应该考虑拥有一个像“Session”这样的对象,它将从头到尾跟踪特定的消息流(来自 1 个客户端)。该对象还应该处理当前状态:主要是缓冲区和处理。每个触发回调的事件必须更新相应会话的状态。Libevent 能够为您提供预定事件的任何结果:成功、失败、超时。每种类型都应反映在您的逻辑中。通常,在处理事件时,请将您的处理逻辑视为具有状态的自动机。

http://en.wikipedia.org/wiki/Reactor_pattern可能是您的任务的好资源。

于 2009-09-21T14:52:56.137 回答
0

让 Client::disconnect() 函数向 EventManager(或服务器)类发送一个事件。这意味着您需要在 EventManager(或服务器)中进行某种事件处理,例如事件循环。

我的一般想法是 Client::disconnect() 不会立即断开客户端,而是在回调完成执行后才断开连接。相反,它只是将事件发布到 EventManager(或服务器)类。

有人可能会争辩说 Client::disconnect() 方法在错误的类上。也许它应该是 Server::disconnect( Client *c )。这将更符合服务器“拥有”客户端并且断开客户端(然后更新一些内部簿记)的服务器的想法。

于 2009-09-21T14:30:12.527 回答