启动服务和监听:
procedure TFrmMain.StartTimerTimer(Sender: TObject);
var
Config: pTConfig;
begin
StartTimer.Enabled := False;
Config := @g_Config;
// 1. 初始化数据库
AccountDB := TFileIDDB.Create(Config.sIdDir + 'Id.DB');
// 2. 启动消息解析线程
ParseList.Resume;
// 3. 等待服务器连接就绪
while (True) do begin
if FrmMasSoc.CheckReadyServers then Break;
Sleep(1);
end;
// 4. 启动网关监听
GSocket.Active := False;
GSocket.Address := Config.sGateAddr; // 监听地址
GSocket.Port := Config.nGatePort; // 监听端口
GSocket.Active := True; // 开始监听
// 5. 启动主循环定时器
ExecTimer.Enabled := True;
end;
- 网络消息处理流程:
// 主循环处理网关消息
procedure TFrmMain.ExecTimerTimer(Sender: TObject);
begin
Config := @g_Config;
try
ProcessGate(Config); // 处理网关消息
finally
bo470D20 := False;
end;
end;
// 处理网关消息
procedure ProcessGate(Config: pTConfig);
begin
EnterCriticalSection(Config.GateCriticalSection);
try
for I := 0 to Config.GateList.Count - 1 do begin
GateInfo := Config.GateList.Items[I];
// 1. 处理网关缓冲区数据
if GateInfo.sReceiveMsg <> '' then begin
DecodeGateData(Config, GateInfo);
// 2. 处理每个用户的消息
for II := 0 to GateInfo.UserList.Count - 1 do begin
UserInfo := GateInfo.UserList.Items[II];
if UserInfo.sReceiveMsg <> '' then
DecodeUserData(Config, UserInfo);
end;
end;
end;
finally
LeaveCriticalSection(Config.GateCriticalSection);
end;
end;
- 消息解析和处理:
// 解析用户数据
procedure DecodeUserData(Config: pTConfig; UserInfo: pTUserInfo);
var
sMsg: string;
DefMsg: TDefaultMessage;
begin
while (True) do begin
if not DecodeMessage(UserInfo.sReceiveMsg, sMsg) then Break;
// 解析消息头
DefMsg := DecodeMessage(sMsg);
// 根据消息类型处理
case DefMsg.Ident of
CM_ADDNEWUSER: // 创建账号
AccountCreate(Config, @DefMsg, UserInfo, sMsg);
CM_UPDATEUSER: // 更新账号
AccountUpdateUserInfo(Config, UserInfo, sMsg);
CM_CHANGEPASSWORD: // 修改密码
AccountChangePassword(Config, UserInfo, sMsg);
CM_IDPASSWORD: // 登录验证
AccountLogin(Config, UserInfo, sMsg);
CM_SELECTSERVER: // 选择服务器
AccountSelectServer(Config, UserInfo, sMsg);
end;
end;
end;
- 账号创建处理:
procedure AccountCreate(Config: pTConfig; Msg: pTDefaultMessage; UserInfo: pTUserInfo; sData: string);
var
nCode: Integer;
DefMsg: TDefaultMessage;
begin
try
// 1. 解析账号数据
DecodeBuffer(sUserEntryMsg, @UserEntry, SizeOf(TUserEntry));
DecodeBuffer(sUserAddEntryMsg, @UserAddEntry, SizeOf(TUserEntryAdd));
// 2. 验证账号格式
if CheckAccountName(UserEntry.sAccount) then begin
// 3. 写入数据库
if AccountDB.Open then begin
if AccountDB.Add(DBRecord) >= 0 then begin
// 写入成功
WriteLogMsg(Config, 'new', UserEntry, UserAddEntry);
nCode := 1;
end;
end;
end;
// 4. 返回结果给客户端
if nCode = 1 then begin
DefMsg := MakeDefaultMsg(SM_NEWID_SUCCESS, 0, 0, 0, 0);
end else begin
DefMsg := MakeDefaultMsg(SM_NEWID_FAIL, nCode, 0, 0, 0);
end;
SendGateMsg(UserInfo.Socket, UserInfo.sSockIndex, EncodeMessage(DefMsg));
end;
end;
- 账号更新处理:
procedure AccountUpdateUserInfo(Config: pTConfig; UserInfo: pTUserInfo; sData: string);
begin
try
// 1. 解析更新数据
DecodeBuffer(sUserEntryMsg, @UserEntry, SizeOf(TUserEntry));
DecodeBuffer(sUserAddEntryMsg, @UserAddEntry, SizeOf(TUserEntryAdd));
// 2. 更新数据库
if AccountDB.Open then begin
if AccountDB.Update(nIndex, DBRecord) >= 0 then begin
WriteLogMsg(Config, 'upd', UserEntry, UserAddEntry);
nCode := 1;
end;
end;
// 3. 返回结果
if nCode = 1 then
DefMsg := MakeDefaultMsg(SM_UPDATEID_SUCCESS, 0, 0, 0, 0)
else
DefMsg := MakeDefaultMsg(SM_UPDATEID_FAIL, nCode, 0, 0, 0);
SendGateMsg(UserInfo.Socket, UserInfo.sSockIndex, EncodeMessage(DefMsg));
end;
end;
主要流程:
graph TD
A[启动服务] --> B[初始化数据库]
B --> C[启动消息解析线程]
C --> D[开始网关监听]
D --> E[主循环处理消息]
E --> F{消息类型}
F -->|创建账号| G[AccountCreate]
F -->|更新账号| H[AccountUpdate]
F -->|修改密码| I[ChangePassword]
F -->|登录验证| J[AccountLogin]
F -->|选服务器| K[SelectServer]
关键点:
- 使用 GSocket 组件监听网关连接
- ExecTimer 定时器循环处理消息
- 消息采用头部标识区分类型
- 使用临界区保护并发访问
- 所有操作都记录日志
- 统一的消息编码解码机制
这样实现了一个完整的登录网关消息处理系统。