首页
社区
课程
招聘
[旧帖] [原创]罗云彬《32位汇编语言》16章中对TCP聊天室程序的扩展1 0.00雪花
发表于: 2009-9-18 21:45 2158

[旧帖] [原创]罗云彬《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直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//