⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nhcnetbase.pas

📁 NetHook API 对战平台内核库是一套实现时下流行的网络对战平台[如浩方、VS]同样功能的通用内核库
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit NhcNetBase;

interface

uses
  Windows, SysUtils, Classes, NhSocketObj;

type

{ Classes }

  TNetIO = class;
  TNetDriver = class;
  TNetHandler = class;

{ TNetIO }
{
  负责底层收发 TCP/UDP 数据,不区分应用层协议。收到数据包后,直接将数据分发
  给各个 NetDriver。NetDriver 也可以直接使用 NetIO 的数据发送功能。
}

  TNetIO = class(TObject)
  private
    FUdpServer: TUdpServer;           // UDP 服务器
    FNetDriverList: TList;            // TNetDriver[]

  private
    procedure RegisterNetDriver(NetDriver: TNetDriver);
    procedure UnregisterNetDriver(NetDriver: TNetDriver);

    function GetFreeUdpPort(StartPort, CheckTimes: Integer): Integer;
    function InitUdpServer(UdpPortStart, CheckPortTimes: Integer): Boolean;

    procedure DoOnUdpServerRecvData(Sender: TObject; const PacketBuffer;
      PacketSize: Integer; const PeerAddr: TPeerAddress);
  public
    constructor Create;
    destructor Destroy; override;

    // 初始化/停止 UDP 服务器
    function InitServer(UdpPortStart, CheckPortTimes: Integer): Boolean;
    procedure StopServer;

    // 处理收到的UDP数据包
    procedure ProcessRecvedUdpPacket(const PacketBuffer; PacketSize: Integer;
      const PeerAddr: TPeerAddress);

    property UdpServer: TUdpServer read FUdpServer;
  end;

{ TNetDriver }
{
  当一个项目中含有多个应用层网络协议时,一个 NetDriver 可以用来处理其中一种
  应用层协议的数据收发事务。需注意的是,NetDriver 只负责该协议之中的数据收发、
  数据包的构建等事宜,并不处理应用层业务逻辑(比如登录、注销操作等等)。

  NetDriver 在收到 NetIO 分发的数据包后,经过适当的转换和处理,再分发给注册
  到该 NetDriver 上的所有 NetHandler。
}

  TNetDriver = class(TObject)
  private
    FNetIO: TNetIO;                     // 所属 NetIO
    FNetHandlerList: TList;             // TNetHandler[]
  private
    procedure RegisterNetHandler(const NetHandler: TNetHandler);
    procedure UnregisterNetHandler(const NetHandler: TNetHandler);
  protected
    // 数据包过滤函数 (返回: True-有效包, False-无效包)
    function FilterUdpPacket(const PacketBuffer; PacketSize: Integer): Boolean; virtual;
    function FilterTcpPacket(Connection: TTcpConnection; const PacketBuffer;
      PacketSize: Integer): Boolean; virtual;

    // 可供覆写的数据分派函数
    procedure DispatchUdpPacket(const PacketBuffer; PacketSize: Integer;
      const PeerAddr: TPeerAddress); virtual;
    procedure DispatchTcpPacket(Connection: TTcpConnection; const PacketBuffer;
      PacketSize: Integer); virtual;

    // 把数据直接递送给 NetHandler
    procedure DeliverUdpPacket(const PacketBuffer; PacketSize: Integer;
      const PeerAddr: TPeerAddress);
    procedure DeliverTcpPacket(Connection: TTcpConnection; const PacketBuffer;
      PacketSize: Integer);
  public
    constructor Create(ANetIO: TNetIO);
    destructor Destroy; override;

    // 初始化、结束化工作
    procedure Initialize; virtual;
    procedure Finalize; virtual;
    // 登录、注销处理
    procedure DoBeforeLogin; virtual;
    procedure DoBeforeLogout; virtual;
    procedure DoAfterLogin; virtual;
    procedure DoAfterLogout; virtual;
    // 垃圾收集
    procedure CollectGarbage; virtual;

    // 供 NetIO 调用的UDP数据分派函数 (执行线程: TImUdpListenerThread)
    procedure ProcessRecvedUdpPacket(const PacketBuffer; PacketSize: Integer;
      const PeerAddr: TPeerAddress);

    property NetIO: TNetIO read FNetIO;
  end;

{ TNetHandler }
{
  NetHandler用于接收来自 NetDriver 的数据,并进行应用层业务逻辑处理。
  一般来说,它只需和 NetDriver 打交道,接收来自 NetDriver 的数据,并调用
  NetDriver 提供的方法来发送数据。

  如果由于程序逻辑需要(比如模块划分),希望将 NetHandler 收到的数据进行再次
  分派,可以在 NetHandler 上注册 NetDispatcher。当然,NetHandler 也可以自己
  接管数据,不再分派。
}

  TNetHandler = class(TObject)
  private
    FNetDriver: TNetDriver;             // 所属 NetDriver

    procedure SetNetDriver(Value: TNetDriver);
  protected
    procedure DispatchUdpPacket(const PacketBuffer; PacketSize: Integer;
      const PeerAddr: TPeerAddress); virtual;
    procedure DispatchTcpPacket(Connection: TTcpConnection; const PacketBuffer;
      PacketSize: Integer); virtual;
  public
    constructor Create; virtual;
    destructor Destroy; override;

    // 初始化、结束化工作
    procedure Initialize; virtual;
    procedure Finalize; virtual;
    // 登录、注销处理
    procedure DoBeforeLogin; virtual;
    procedure DoBeforeLogout; virtual;
    procedure DoAfterLogin; virtual;
    procedure DoAfterLogout; virtual;
    // 垃圾收集
    procedure CollectGarbage; virtual;

    // 取得或设置所属 NetDriver
    property NetDriver: TNetDriver read FNetDriver write SetNetDriver;
  end;

implementation

{ TNetIO }

constructor TNetIO.Create;
begin
  inherited Create;

  FNetDriverList := TList.Create;
  FUdpServer := TUdpServer.Create;

  FUdpServer.OnRecvData := DoOnUdpServerRecvData;
end;

destructor TNetIO.Destroy;
begin
  FNetDriverList.Free;
  FUdpServer.Free;
  inherited;
end;

//-----------------------------------------------------------------------------
// 描述: 注册 NetDriver
//-----------------------------------------------------------------------------
procedure TNetIO.RegisterNetDriver(NetDriver: TNetDriver);
begin
  if FNetDriverList.IndexOf(Pointer(NetDriver)) = -1 then
    FNetDriverList.Add(NetDriver);
end;

//-----------------------------------------------------------------------------
// 描述: 注销 NetDriver
//-----------------------------------------------------------------------------
procedure TNetIO.UnregisterNetDriver(NetDriver: TNetDriver);
begin
  FNetDriverList.Remove(NetDriver);
end;

//-----------------------------------------------------------------------------
// 描述: 取得空闲UDP端口号
// 参数:
//   StartPort  - 起始端口号
//   CheckTimes - 检测次数
// 返回:
//   空闲端口号 (若失败则返回 0)
//-----------------------------------------------------------------------------
function TNetIO.GetFreeUdpPort(StartPort, CheckTimes: Integer): Integer;
begin
  Result := GetFreePort(nptUdp, StartPort, CheckTimes);
end;

//-----------------------------------------------------------------------------
// 描述: 初始化UDP服务器
// 参数:
//   UdpPortStart   - 起始 UDP 端口
//   CheckPortTimes - 从起始端口开始,尝试扫描多少个端口 (若为0,则表示固定端口)
//-----------------------------------------------------------------------------
function TNetIO.InitUdpServer(UdpPortStart, CheckPortTimes: Integer): Boolean;
const
  RetryTimes = 5;
var
  I, Port: Integer;
begin
  for I := 1 to RetryTimes do
  begin
    if CheckPortTimes > 0 then
      Port := GetFreeUdpPort(UdpPortStart, CheckPortTimes)
    else
      Port := UdpPortStart;

    Result := (Port <> 0);
    if Result then
    begin
      try
        FUdpServer.Active := False;
        FUdpServer.LocalPort := Port;
        FUdpServer.Active := True;
        Break;
      except
        Result := False;
      end;
    end;
  end;
end;

//-----------------------------------------------------------------------------
// 描述: FUdpServer 的数据接收事件处理
//-----------------------------------------------------------------------------
procedure TNetIO.DoOnUdpServerRecvData(Sender: TObject; const PacketBuffer;
  PacketSize: Integer; const PeerAddr: TPeerAddress);
begin
  ProcessRecvedUdpPacket(PacketBuffer, PacketSize, PeerAddr);
end;

//-----------------------------------------------------------------------------
// 描述: 初始化UDP服务器
// 参数:
//   UdpPortStart   - 起始 UDP 端口
//   CheckPortTimes - 从起始端口开始,尝试扫描多少个端口 (若为0,则表示固定端口)
// 返回:
//   True  - 成功
//   False - 失败
//-----------------------------------------------------------------------------
function TNetIO.InitServer(UdpPortStart, CheckPortTimes: Integer): Boolean;
begin
  Result := InitUdpServer(UdpPortStart, CheckPortTimes);
  if not Result then
    FUdpServer.Active := False;
end;

//-----------------------------------------------------------------------------
// 描述: 停止服务器
//-----------------------------------------------------------------------------
procedure TNetIO.StopServer;
begin
  FUdpServer.Close;
end;

//-----------------------------------------------------------------------------
// 描述: NetIO 收到 UDP 包后,分派给 NetDriver.
//-----------------------------------------------------------------------------
procedure TNetIO.ProcessRecvedUdpPacket(const PacketBuffer; PacketSize: Integer;
  const PeerAddr: TPeerAddress);
var
  I: Integer;
begin
  if PacketSize <= 0 then Exit;

  for I := 0 to FNetDriverList.Count - 1 do
    TNetDriver(FNetDriverList[I]).ProcessRecvedUdpPacket(PacketBuffer, PacketSize, PeerAddr);
end;

{ TNetDriver }

constructor TNetDriver.Create(ANetIO: TNetIO);
begin
  inherited Create;
  FNetIO := ANetIO;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -