📄 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 + -