-
-
[旧帖] [原创]罗云彬《32位汇编语言》16章中对TCP聊天室程序的扩展1 0.00雪花
-
发表于: 2009-9-18 21:45 2158
-
大家好,在罗云彬的《windows环境下32位汇编语言程序设计》第十六章中有一个阻塞模式下TCP聊天室的小程序。作者最后还提出了四个小问题:1.在聊天信息中加入用户发言的时间;2.限制用户灌水;3.限制用户重复登录;4.实现悄悄话的功能。我经过一段时间的调试,把这几个小功能都实现了。现在把我的思路写下,供大家参考。
在聊天信息中加入用户发言的时间:
1.在Message.inc中,改变MSG_DOWN结构体。
MSG_DOWN struct
szTime db 20 dup (?) ;canmeng萌1
szSender db 12 dup (?) ;消息发送者
dwLength dd ? ;后面内容字段的长度
szContent db 256 dup (?) ;内容,不等长,长度由dwLength指定
MSG_DOWN ends
发言时间我定义为如下格式:2009-12-17 12:13:56,占19个字节,再加上用于结尾的0字符,正好占20个字节。所以定义szTime为20个字节。
2.在_MsgQueue.asm中,
①改变消息结构体
MSG_QUEUE_ITEM struct ;队列中单条消息的格式定义
dwMessageId dd ? ;消息编号
szSender db 12 dup (?) ;发送者
szContent db 256 dup (?) ;聊天内容
szTime db 20 dup (?) ;canmeng萌1
MSG_QUEUE_ITEM ends
②在.data?段中定义一个SYSTEMTIME类型的变量_szTime
_szTime SYSTEMTIME <?> ;canmeng萌1
定义六个双字类型的全局变量sztemp1,sztemp2,sztemp3,sztemp4,sztemp5,sztemp6,分别用来存放所返回的时间的年、月、日、时、分、秒。
sztemp1 dd ? ;canmeng萌1
sztemp2 dd ? ;canmeng萌1
sztemp3 dd ? ;canmeng萌1
sztemp4 dd ? ;canmeng萌1
sztemp5 dd ? ;canmeng萌1
sztemp6 dd ? ;canmeng萌1
再定义一个128个字节的缓冲区变量szTimeBuffer,用来存放返回的时间。
szTimeBuffer db 128 dup (?) ;canmeng萌1
③在.const段中顶一个变量szTimeStyle,用它来规定时间的格式。
.const ;canmeng萌1
szTimeStyle db '%d-%d-%d %d:%d:%d',0 ;canmeng萌1
④修改_InsertMsgQueue函数
准确的说,放到消息队列中去的不是用户发言时的时间,而是用户把聊天语句发给服务器后,服务器把这条聊天语句插入到消息队列时的时间。
调用GetLocalTime函数,经过处理后得到所需要的时间。
invoke GetLocalTime,addr _szTime ;canmeng萌1,获得当前系统时间
movzx eax,_szTime.wYear ;canmeng萌1
mov sztemp1,eax ;canmeng萌1
movzx eax,_szTime.wMonth ;canmeng萌1
mov sztemp2,eax ;canmeng萌1
movzx eax,_szTime.wDay ;canmeng萌1
mov sztemp3,eax ;canmeng萌1
movzx eax,_szTime.wHour ;canmeng萌1
mov sztemp4,eax ;canmeng萌1
movzx eax,_szTime.wMinute ;canmeng萌1
mov sztemp5,eax ;canmeng萌1
movzx eax,_szTime.wSecond ;canmeng萌1
mov sztemp6,eax ;canmeng萌1
invoke wsprintf,addr szTimeBuffer,addr szTimeStyle,sztemp1,sztemp2,\
sztemp3,sztemp4,sztemp5,sztemp6 ;canmeng萌1
invoke lstrcpy,addr [esi].szTime,addr szTimeBuffer ;canmeng萌1,这样消息中就包含聊天的时间了
⑤修改_GetMsgFromQueue函数
_GetMsgFromQueue的参数加上一个_lpszTime参数,它代表一个缓冲区指针,这个缓冲区用来存放消息中的szTime字段中的时间。
_GetMsgFromQueue proc _dwMessageId,_lpszSender,_lpszContent,_lpszTime ;canmeng萌1
invoke lstrcpy,_lpszTime,addr [esi].szTime ;canmeng萌1
3.在Server.asm中,当服务器端的某一个线程收到对应的客户端发来的聊天语句时(MSG_UP数据包),就会调用_InsertMsgQueue函数添加上当前时间把本条消息放到消息队列中,然后再调用_GetMsgFromQueue函数把消息取出,组成一个MSG_DOWN结构体,发送出去。服务器是通过_SendMsgFromQueue间接调用_GetMsgFromQueue的。由于_GetMsgFromQueue已经多了一个输入参数,所以也要修改_SendMsgFromQueue函数。
在_SendMsgFromQueue中,
Invoke _GetMsgFromQueue,ecx,addr [esi].MsgDown.szSender,addr [esi].MsgDown.szContent,\
addr [esi].MsgDown.szTime ;canmeng萌1
4.在Client1.asm中,当客户端收到服务器端发来的MSG_DOWN数据包时,只需要把其中的szTime字段的值提取出来并显示就行了。
把收到数据包后的处理语句修改为如下格式:
;********************************************************************
; 循环接收消息
;********************************************************************
.if @stMsg.MsgHead.dwCmdId == CMD_MSG_DOWN
invoke lstrcpy,addr @szBuffer,addr @stMsg.MsgDown.szContent ;canmeng萌1,先显示内容
invoke SendDlgItemMessage,hWinMain,IDC_INFO,LB_INSERTSTRING,0,addr @szBuffer
invoke lstrcpy,addr @szBuffer,addr @stMsg.MsgDown.szSender
invoke lstrcat,addr @szBuffer,addr szSpar
invoke lstrcat,addr @szBuffer,addr @stMsg.MsgDown.szTime ;canmeng萌1
invoke SendDlgItemMessage,hWinMain,IDC_INFO,LB_INSERTSTRING,0,addr @szBuffer;canmeng萌1
.endif
这样,第一步完成了。可以正常显示时间了。呵呵
附件中是经过修改的源代码,在修改的地方我都做了标记。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课