原始翎风CLIENT8位 (6) frmMain中的网络消息的处理流程接受消息处理

frmMain中的网络消息的处理流程接受消息处理

TfrmMain.CSocketRead 接收服务器传来的消息,字符串格式,
如果字符串中有*号,去掉* 号 ,并 回传 * 号给服务器
没有 * 号的 字符串加入到SocStr字符串变量中

 

Timer1Timer,定时器 10毫秒
设置 开关,锁定,避免重复进入

SocStr 加入到 BufferStr中,SocStr清空
BufferStr 字符大于2 就不断处理,
跳出条件地图移动等待中了,
检测没有!字符 跳出
取得# !之间的字符串放到 data中
DecodeMessagePacket (data); //解码并按消息的命令处理

解锁。

有点像是双缓冲?
SOCKET接受到的服务器消息(字符串格式) 加入到SocStr 中,

定时器中,SocStr加入到BufferStr,SocStr清空
不断的取得BufferStr# !之间的字符串放到 data中,剩下的放回BufferStr,直到BufferStr空,少于2个字符,里面没有!号了或 其它条件如地图移动跳出
DecodeMessagePacket (data); //解码并按消息的命令处理
1,定时器有锁定判断,避免重复进入处理,

????但是 Timer中的代码如果没有执行完的话,是不会触发下一次定时事件的.


问题?为什么只判读!不判断 #?


TfrmMain.DecodeMessagePacket (datablock: string)
消息开头缩写 SM 大概就是ServerMessage 服务器消息的意思。


TfrmMain.FormCreate 中初始赋值

SocStr := ''

TfrmMain.CSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);

网络连接上
SocStr := '';
BufferStr := '';


procedure TfrmMain.CSocketRead(Sender: TObject; Socket: TCustomWinSocket);

处理后SocStr := SocStr + data;
var
n: integer;
data, data2: string;
begin
data := Socket.ReceiveText;
//if pos('GOOD', data) > 0 then DScreen.AddSysMsg (data);

n := pos('*', data);//收到的字符串里面有* 字符,去掉* ,再回一个* 字符
if n > 0 then begin
data2 := Copy (data, 1, n-1); //拷贝*之前的 字符串
data := data2 + Copy (data, n+1, Length(data)); //去掉第一个 * 字符 这里Length(data)应该超长了
//SendSocket ('*');
CSocket.Socket.SendText ('*'); //发送*是 什么意思?
end;
SocStr := SocStr + data; 收到的加入SocStr
end;


procedure TfrmMain.DecodeMessagePacket (datablock: string);

TfrmMain.Timer1Timer(Sender: TObject); //常使能,间隔非常小仅仅 10
中调用 但是 Timer中的代码如果没有执行完的话,是不会触发下一次定时事件的.
在一个快速循环中,
去主动执行,调取,拉动一个事件去判断,
而不是去 看一个 被动的事件设置的 变量?


不是的,


busy := TRUE; //设置 开关,避免重复进入
try
BufferStr := BufferStr + SocStr; // data := Socket.ReceiveText; SocStr := SocStr + data
SocStr := '';
if BufferStr <> '' then begin
mcnt := 0;
while Length(BufferStr) >= 2 do begin
if g_boMapMovingWait then break; // 地图移动等待
if Pos('!', BufferStr) <= 0 then break; //检测没有!字符 跳出
BufferStr := ArrestStringEx (BufferStr, '#', '!', data); //作用取得# !之间的字符串放到 data中,返回# !之后的字符串,或者空串
if data = '' then break;
DecodeMessagePacket (data); //解码并按消息的命令处理
if Pos('!', BufferStr) <= 0 then break;
end;
end;
finally
busy := FALSE; //解锁
end;


TfrmMain.DecodeMessagePacket (datablock: string)

//---------------第1种格式 +PWR/[tick]------------------
字符明文
打开攻杀PWR
打开刺杀LNG 关闭刺杀ULNG
打开半月WID 关闭半月UWID
打开烈火FIR 关闭烈火 UFIR
GOOD ActionLock := FALSE
FAIL
不为'' 时间判断CheckSpeedHack

ActionLock := FALSE;
Inc(g_nReceiveCount);
ActionFailLock := TRUE;
ActionFailLockTime
g_MySelf.MoveFail 这些值是用来做什么的?

--------------第2种格式 =DIG 小于16字节的-------
字符明文
=DIG


-------第3种格式------大于16字节EFBLOCKSIZE----------
需要解码
16字节放入 head
16字节后放入 body
msg := DecodeMessage (head)

知识点 1
这里就涉及到一个编码解码,有个专门的文件EDcode.pas
用的就是老版本的,没有进行加密。只是进行了Base64编码,而且不太像是标准的Base64编码,有点小改动?
这样做应该是因为Base64算法很好地解决了非ASCII码字符的传输问题,譬如中文字符的传输问题。
这个单元和服务器源码单元 一起使用的,应为JSOCKET 传输的是字符串。

将整个框架理解了在来学习这个?

知识点2
消息的记录结构,定义 这几个。 解码后进行装载
TDefaultMessage TChrMsg TShortMessage TMessageBodyW TMessageBodyWL TCharDesc

 

 

开关g_boShowMemoLog判断,ShowHumanMsg(@Msg)显示指定角色的消息

还没有人物的一些消息处理
case
帐号建立,删除 ,升级账户,密码,选择服务器, 选择角色

地图更换情况下处理

case
游戏程序版本不正确
新地图
人物登陆上SM_LOGON,
服务器配置 SM_SERVERCONFIG
重新连接 SM_RECONNECT
地图描叙SM_MAPDESCRIPTION
SM_GAMEGOLDNAME
SM_ADJUST_BONUS
SM_MYSTATUS
动作,行为 SM_TURN, SM_BACKSTEP,SM_SPACEMOVE_HIDE,SM_WALK, SM_RUSH, SM_RUSHKUNG,SM_RUN,SM_HORSERUN,SM_HIT,SM_SPELL
SM_WINEXP SM_OPENHEALTH: 讲话 SM_SHOWEVENT 包裹,掉落物品 ,物品显示,开门,装备上,使用物品,负重
SM_FEATURECHANGED SM_EAT_OK吃药? SM_ADDMAGIC 商人,交易有关 的消息 SM_MERCHANTSAY 买卖 修理 仓库处理 SM_STORAGE_OK
SM_716?绘画效果人物?组队消息的处理 玩家交易消息的处理,行会消息的处理
SM_PLAYDICE 玩骰子?

这些大多都会再调用一个ClientGetSend***(MSG)的 过程来
CASE 只是进行分配,或者简单的处理下进行分配到具体的 功能过程来处理,或者是对某个全局开关变量设置?
或者是打开有关的对话框。


------------第4种格式,有'#' 字符,-----------
明文

放入到系统显示消息里面处理。DScreen.AddSysMsg,加入到m_SysMsgList 中去了

 

posted @ 2023-11-28 22:37  D7mir  阅读(109)  评论(0)    收藏  举报