第一步的功能已经实现了。下一步就是限制用户灌水了。
1.在Message.inc中,增加一个MSG_UP_RESP数据包,服务器端收到客户端发来的聊天语句时,如果判断本客户端此次的发言时间和上次的发言时间间隔太短,就向客户端发送带错误代码的MSG_UP_RESP数据包。

;**********************************************************  ;canmeng萌2
; 提示语句(服务器端->客户端)                  ;canmeng萌2
;**********************************************************  ;canmeng萌2
MSG_UP_RESP    struct            ;canmeng萌2
  dbResult    db  ?              ;canmeng萌2
MSG_UP_RESP    ends            ;canmeng萌2
②增加这个数据包的数据包头部命令ID
CMD_MSG_UP_RESP  equ    84h  ;服务器端 ->客户端,提示不可以灌水,canmeng萌2
③在MSG_STRUCT结构体中也增加一个MSG_UP_RESP类型的字段
MSG_STRUCT    struct
  MsgHead    MSG_HEAD <>
  union
    Login    MSG_LOGIN <>
    LoginResp    MSG_LOGIN_RESP <>
    MsgUp    MSG_UP <>
    MsgUpResp    MSG_UP_RESP <>    ;canmeng萌2
    MsgDown    MSG_DOWN <>
  ends
MSG_STRUCT    ends
2.在Server.asm中,在_ServiceThread子线程中定义一个局部变量@lasttime,用来记录本子线程和对应的客户端最近一次通话的时间。

local  @lasttime          ;canmeng萌2
②当服务器端的某个线程收到对应的客户端发来的聊天语句时,首先把此用户上次的发言时间赋给@lasttime,然后再调用GetTickCount函数得到现在的时间并赋给[edi].dwLastTime
两个进行比较,如果间隔小于设定的时间间隔(我设定为2秒),那么就向对应的客户端发送一个MSG_UP_RESP数据包,而且不把本次的聊天语句放进消息队列。
;********************************************************************
; 使用 select 函数等待 200ms,如果没有接收到数据包则循环
;********************************************************************
invoke  _WaitData,_hSocket,200 * 1000
.break  .if eax == SOCKET_ERROR
.if  eax
  invoke  _RecvPacket,_hSocket,esi,sizeof @szBuffer
  .break  .if eax
  mov eax,[edi].dwLastTime                    ;canmeng萌2
  mov   @lasttime,eax                      ;canmeng萌2
  invoke  GetTickCount
  mov  [edi].dwLastTime,eax
  .if  [esi].MsgHead.dwCmdId == CMD_MSG_UP
  mov  ebx,[edi].dwLastTime                    ;canmeng萌2
  sub  ebx,@lasttime                        ;canmeng萌2
  .if ebx<2000                          ;canmeng萌2
    mov [esi].MsgHead.dwCmdId,CMD_MSG_UP_RESP        ;canmeng萌2
    mov [esi].MsgHead.dwLength,sizeof MSG_HEAD+sizeof MSG_UP_RESP  ;canmeng萌2
    mov [esi].MsgUpResp.dbResult,1              ;canmeng萌2
    invoke send,_hSocket,esi,[esi].MsgHead.dwLength,0  ;canmeng萌2
  .else                              ;canmeng萌2
    invoke  _InsertMsgQueue,addr [edi].szUserName,addr [esi].MsgUp.szContent
  .endif                  ;canmeng萌2
  .endif
  .endif
.endw
3.在Client1.asm中,
①在.const段中定义一个变量zstoofast,当用户发言太快时就显示这个提示。
.const
sztoofast  db  '您的发言太快,请休息片刻',0        ;canmeng萌2
②在_workThread的“循环接收消息”中进行判断,如果接受的数据包命令ID为CMD_MSG_UP_RESP,那么就显示一个消息框。
.if  @stMsg.MsgHead.dwCmdId == CMD_MSG_DOWN
……
.elseif  @stMsg.MsgHead.dwCmdId == CMD_MSG_UP_RESP      ;canmeng萌2
  .if  @stMsg.MsgUpResp.dbResult==1              ;canmeng萌2
  invoke  MessageBox,hWinMain,addr sztoofast,NULL,MB_OK    ;canmeng萌2
  .endif                              ;canmeng萌2
这样,第二步限制用户灌水也完成了。
附件是源代码。

上传的附件 2防止用户灌水.rar