?? nhcnetbase.pas
字號:
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 + -