首页
社区
课程
招聘
[求助]朋友们晚上好!小弟由于光盘丢了!急需一份WIN32ASM 罗云斌第二版 网络编程代码
发表于: 2007-11-27 18:46 5777

[求助]朋友们晚上好!小弟由于光盘丢了!急需一份WIN32ASM 罗云斌第二版 网络编程代码

2007-11-27 18:46
5777
朋友们晚上好!由于我的WIN32ASM 罗云斌第二版 光盘丢失了
现在学到书本第16章网络 一个配置TCP Stream套接字服务器的问题

我不知道如何维护一个消息队列来群聊 是服务器端的代码

由于书上的代码不全 光盘又丢了,想不出来 ~!特来看雪求救!!
希望有源代码的朋友共享个给我 谢谢 !!最好是全代码  如果没有 就Server.asm 也行
!!!!
好了 ....wait....

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
Server.asm:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 2nd Edition>
; by 罗云彬, http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Server.asm
; 使用 TCP 协议的聊天室例子程序 —— 服务器端
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Server.asm
; rc Server.rc
; Link /subsystem:windows Server.obj Server.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .386
                .model flat, stdcall
                option casemap :none   ; case sensitive
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include                windows.inc
include                user32.inc
includelib        user32.lib
include                kernel32.inc
includelib        kernel32.lib
include                wsock32.inc
includelib        wsock32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN        equ        1000
DLG_MAIN        equ        2000
IDC_COUNT        equ        2001
TCP_PORT        equ        9999
;********************************************************************
; 客户端会话信息
;********************************************************************
SESSION                struct
  szUserName        db        12 dup (?)        ; 用户名
  dwMessageId        dd        ?                ; 已经下发的消息编号
  dwLastTime        dd        ?                ; 链路最近一次活动的时间
SESSION                ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .data?
hInstance        dd        ?
hWinMain        dd        ?
hListenSocket        dd        ?
dwThreadCounter        dd        ?
dwFlag                dd        ?
F_STOP                equ        0001h

                .const
szErrBind        db        '无法绑定到TCP端口9999,请检查是否有其它程序在使用!',0
szSysInfo        db        '系统消息',0
szUserLogin        db        ' 进入了聊天室!',0
szUserLogout        db        ' 退出了聊天室!',0

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .code
include                _Message.inc
include                _SocketRoute.asm
include                _MsgQueue.asm

                assume        esi:ptr MSG_STRUCT,edi:ptr SESSION
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 循环取消息队列中的聊天语句并发送到客户端,直到全部消息发送完毕
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_SendMsgQueue        proc        uses esi edi _hSocket,_lpBuffer,_lpSession
                local        @stMsg:MSG_STRUCT

                mov        esi,_lpBuffer
                mov        edi,_lpSession
                .while        ! (dwFlag & F_STOP)
                        mov        ecx,[edi].dwMessageId
                        inc        ecx
                        invoke        _GetMsgFromQueue,ecx,addr [esi].MsgDown.szSender,addr [esi].MsgDown.szContent
                        .break        .if ! eax
                        mov        [edi].dwMessageId,eax
                        invoke        lstrlen,addr [esi].MsgDown.szContent
                        inc        eax
                        mov        [esi].MsgDown.dwLength,eax
                        add        eax,sizeof MSG_HEAD+MSG_DOWN.szContent
                        mov        [esi].MsgHead.dwLength,eax
                        mov        [esi].MsgHead.dwCmdId,CMD_MSG_DOWN
                        invoke        send,_hSocket,esi,[esi].MsgHead.dwLength,0
                        .break        .if eax == SOCKET_ERROR
                        invoke        GetTickCount
                        mov        [edi].dwLastTime,eax
;********************************************************************
                        invoke        _WaitData,_hSocket,0
                        .break        .if eax == SOCKET_ERROR
                        .if        eax
                                xor        eax,eax
                                .break
                        .endif
;********************************************************************
                .endw
                ret

_SendMsgQueue        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 检测链路的最后一次活动时间
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_LinkCheck        proc        uses esi edi _hSocket,_lpBuffer,_lpSession

;********************************************************************
; 查看是否需要检测链路(30秒内没有数据通信则发送链路检测包)
;********************************************************************
                invoke        GetTickCount
                push        eax
                sub        eax,[edi].dwLastTime
                cmp        eax,30 * 1000
                pop        eax
                jb        _Ret
                @@:
                mov        [edi].dwLastTime,eax
                mov        [esi].MsgHead.dwCmdId,CMD_CHECK_LINK
                mov        [esi].MsgHead.dwLength,sizeof MSG_HEAD
                invoke        send,_hSocket,esi,[esi].MsgHead.dwLength,0
                cmp        eax,SOCKET_ERROR
                jnz        _Ret
                ret
_Ret:
                xor        eax,eax
                ret

_LinkCheck        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 通讯服务线程:每个客户端登录的连接将产生一个线程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ServiceThread        proc        _hSocket
                local        @stSession:SESSION,@szBuffer[512]:byte

                pushad
                inc        dwThreadCounter
                invoke        SetDlgItemInt,hWinMain,IDC_COUNT,dwThreadCounter,FALSE

                lea        esi,@szBuffer
                lea        edi,@stSession
                invoke        RtlZeroMemory,edi,sizeof @stSession
                mov        eax,dwSequence
                mov        [edi].dwMessageId,eax
;********************************************************************
; 用户名和密码检测,为了简化程序,现在可以使用任意用户名和密码
;********************************************************************
                invoke        _RecvPacket,_hSocket,esi,sizeof @szBuffer
                or        eax,eax
                jnz        _Ret
                .if        [esi].MsgHead.dwCmdId != CMD_LOGIN
                        jmp        _Ret
                .else
                        invoke        lstrcpy,addr [edi].szUserName,addr [esi].Login.szUserName
                        mov        [esi].LoginResp.dbResult,0
                .endif
                mov        [esi].MsgHead.dwCmdId,CMD_LOGIN_RESP
                mov        [esi].MsgHead.dwLength,sizeof MSG_HEAD+sizeof MSG_LOGIN_RESP
                invoke        send,_hSocket,esi,[esi].MsgHead.dwLength,0
                cmp        eax,SOCKET_ERROR
                jz        _Ret
                cmp        [esi].LoginResp.dbResult,0
                jnz        _Ret
;********************************************************************
; 广播:xxx 进入了聊天室
;********************************************************************
                invoke        lstrcpy,esi,addr [edi].szUserName
                invoke        lstrcat,esi,addr szUserLogin
                invoke        _InsertMsgQueue,addr szSysInfo,esi
                invoke        GetTickCount
                mov        [edi].dwLastTime,eax
;********************************************************************
; 循环处理消息
;********************************************************************
                .while        ! (dwFlag & F_STOP)
                        invoke        _SendMsgQueue,_hSocket,esi,edi
                        .break        .if eax
                        invoke        _LinkCheck,_hSocket,esi,edi
                        .break        .if eax
                        .break        .if dwFlag & F_STOP
;********************************************************************
; 使用 select 函数等待 200ms,如果没有接收到数据包则循环
;********************************************************************
                        invoke        _WaitData,_hSocket,200 * 1000
                        .break        .if eax == SOCKET_ERROR
                        .if        eax
                                invoke        _RecvPacket,_hSocket,esi,sizeof @szBuffer
                                .break        .if eax
                                invoke        GetTickCount
                                mov        [edi].dwLastTime,eax
                                .if        [esi].MsgHead.dwCmdId == CMD_MSG_UP
                                        invoke        _InsertMsgQueue,addr [edi].szUserName,addr [esi].MsgUp.szContent
                                .endif
                        .endif
                .endw
;********************************************************************
; 广播:xxx 退出了聊天室
;********************************************************************
                invoke        lstrcpy,esi,addr [edi].szUserName
                invoke        lstrcat,esi,addr szUserLogout
                invoke        _InsertMsgQueue,addr szSysInfo,addr @szBuffer
;********************************************************************
; 关闭 socket
;********************************************************************
_Ret:
                invoke        closesocket,_hSocket
                dec        dwThreadCounter
                invoke        SetDlgItemInt,hWinMain,IDC_COUNT,dwThreadCounter,FALSE
                popad
                ret

_ServiceThread        endp
                assume        esi:nothing,edi:nothing
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 监听线程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ListenThread        proc        _lParam
                local        @stSin:sockaddr_in

;********************************************************************
; 创建 socket
;********************************************************************
                invoke        socket,AF_INET,SOCK_STREAM,0
                mov        hListenSocket,eax

                invoke        RtlZeroMemory,addr @stSin,sizeof @stSin
                invoke        htons,TCP_PORT
                mov        @stSin.sin_port,ax
                mov        @stSin.sin_family,AF_INET
                mov        @stSin.sin_addr,INADDR_ANY
                invoke        bind,hListenSocket,addr @stSin,sizeof @stSin
                .if        eax
                        invoke        MessageBox,hWinMain,addr szErrBind,\
                                NULL,MB_OK or MB_ICONSTOP
                        invoke        ExitProcess,NULL
                        ret
                .endif
;********************************************************************
; 开始监听,等待连接进入并为每个连接创建一个线程
;********************************************************************
                invoke        listen,hListenSocket,5
                .while        TRUE
                        invoke        accept,hListenSocket,NULL,0
                        .break        .if eax == INVALID_SOCKET
                        push        ecx
                        invoke        CreateThread,NULL,0,offset _ServiceThread,eax,NULL,esp
                        pop        ecx
                        invoke        CloseHandle,eax
                .endw
                invoke        closesocket,hListenSocket
                ret

_ListenThread        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 主窗口程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain        proc        uses ebx edi esi hWnd,wMsg,wParam,lParam
                local        @stWsa:WSADATA

                mov        eax,wMsg
;********************************************************************
                .if        eax ==        WM_INITDIALOG
                        push        hWnd
                        pop        hWinMain
                        invoke        LoadIcon,hInstance,ICO_MAIN
                        invoke        SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
                        invoke        InitializeCriticalSection,addr stCS
                        invoke        WSAStartup,101h,addr @stWsa
                        push        ecx
                        invoke        CreateThread,NULL,0,offset _ListenThread,0,NULL,esp
                        pop        ecx
                        invoke        CloseHandle,eax
;********************************************************************
                .elseif        eax ==        WM_CLOSE
                        invoke        closesocket,hListenSocket
                        or        dwFlag,F_STOP
                        .while        dwThreadCounter
                        .endw
                        invoke        WSACleanup
                        invoke        DeleteCriticalSection,addr stCS
                        invoke        EndDialog,hWinMain,NULL
;********************************************************************
                .else
                        mov        eax,FALSE
                        ret
                .endif
                mov        eax,TRUE
                ret

_ProcDlgMain        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 程序开始
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
                invoke        GetModuleHandle,NULL
                mov        hInstance,eax
                invoke        DialogBoxParam,eax,DLG_MAIN,NULL,offset _ProcDlgMain,0
                invoke        ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                end        start
2007-11-27 19:01
0
雪    币: 290
活跃值: (11)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
3
感谢Scor
2007-11-27 19:05
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
共享万岁嘛
2007-11-27 19:07
0
雪    币: 290
活跃值: (11)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
5
请再发个_MsgQueue给我好吗
我就是消息队列处理不知道  谢谢

刚才我没说清楚
是Server.asm 里面的关联代码
2007-11-27 19:09
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
_MsgQueue.inc:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 2nd Edition>
; by 罗云彬, http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 TCP 协议的聊天室例子程序
; 通讯链路传输的数据结构定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
;
;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
CMD_LOGIN        equ        01h        ; 客户端 ->服务器端,登录
CMD_LOGIN_RESP        equ        81h        ; 服务器端 -> 客户端,登录回应
CMD_MSG_UP        equ        02h        ; 客户端 -> 服务器端,聊天语句
CMD_MSG_DOWN        equ        82h        ; 服务器端 -> 客户端,聊天语句
CMD_CHECK_LINK        equ        83h        ; 服务器端 -> 客户端,链路检测
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据包定义方式
; 每个数据包以 MSG_HEAD + MSG_xxx 组成,整个长度填入 MSG_HEAD.dwLength
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;********************************************************************
; 数据包头部,所有的数据包都以 MSG_HEAD 开头
;********************************************************************
MSG_HEAD                struct
  dwCmdId                dw        ?                ;命令ID
  dwLength                dd        ?                ;整个数据包长度=数据包头部+数据包体
MSG_HEAD                ends
;********************************************************************
; 登录数据包(客户端->服务器端)
;********************************************************************
MSG_LOGIN                struct
  szUserName                db        12 dup (?)        ;用户登录ID
  szPassword                db        12 dup (?)        ;登录密码
MSG_LOGIN                ends
;********************************************************************
; 登录回应数据包(服务器端->客户端)
;********************************************************************
MSG_LOGIN_RESP                struct
  dbResult                db        ?                ;登录结果:0=成功,1=用户名或密码错
MSG_LOGIN_RESP                ends
;********************************************************************
; 聊天语句(客户端->服务器端):不等长数据包
;********************************************************************
MSG_UP                        struct
  dwLength                dd        ?                ;后面内容字段的长度
  szContent                db        256 dup (?)        ;内容,不等长,长度由dwLength指定
MSG_UP                        ends
;********************************************************************
; 聊天语句(服务器端->客户端):不等长数据包
;********************************************************************
MSG_DOWN                struct
  szSender                db        12 dup (?)        ;消息发送者
  dwLength                dd        ?                ;后面内容字段的长度
  szContent                db        256 dup (?)        ;内容,不等长,长度由dwLength指定
MSG_DOWN                ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
MSG_STRUCT                struct
  MsgHead                MSG_HEAD <>
  union
    Login                MSG_LOGIN <>
    LoginResp                MSG_LOGIN_RESP <>
    MsgUp                MSG_UP <>
    MsgDown                MSG_DOWN <>
  ends
MSG_STRUCT                ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_MsgQueue.asm:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 2nd Edition>
; by 罗云彬, http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; FIFO(First in, first out)消息队列的实现
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
;
;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
QUEUE_SIZE        equ        100                ;消息队列的长度
MSG_QUEUE_ITEM        struct                        ;队列中单条消息的格式定义
  dwMessageId        dd        ?                ;消息编号
  szSender        db        12 dup (?)        ;发送者
  szContent        db        256 dup (?)        ;聊天内容
MSG_QUEUE_ITEM        ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                .data?

stCS                CRITICAL_SECTION <?>
stMsgQueue        MSG_QUEUE_ITEM QUEUE_SIZE dup (<?>)
dwMsgCount        dd        ?                ;队列中当前消息数量

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                .data

dwSequence        dd        1        ;消息序号,从1开始

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 在队列中加入一条消息
; -- 如果队列已经满了,则将整个队列前移一个位置,相当于最早的消息被覆盖
;    然后在队列尾部空出的位置加入新消息
; -- 如果队列未满,则在队列的最后加入新消息
; -- 消息编号从1开始递增,这样保证队列中各消息的编号是连续的
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 入口:_lpszSender = 指向发送者字符串的指针
;        _lpszContent = 指向聊天语句内容字符串的指针
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_InsertMsgQueue        proc        _lpszSender,_lpszContent

                pushad
                invoke        EnterCriticalSection,addr stCS
                mov        eax,dwMsgCount
;********************************************************************
; 如果队列满,则移动队列,并在队列尾部添加新消息
;********************************************************************
                .if        eax >= QUEUE_SIZE
                        mov        edi,offset stMsgQueue
                        mov        esi,offset stMsgQueue + sizeof MSG_QUEUE_ITEM
                        mov        ecx,(QUEUE_SIZE-1) * sizeof MSG_QUEUE_ITEM
                        mov        eax,ecx
                        cld
                        rep        movsb
;********************************************************************
; 否则直接添加到队列尾部
;********************************************************************
                .else
                        inc        dwMsgCount
                        mov        ecx,sizeof MSG_QUEUE_ITEM
                        mul        ecx
                .endif
;********************************************************************
; 前面的语句执行完毕后,eax指向队列中空位置的偏移量
;********************************************************************
                lea        esi,[stMsgQueue+eax]
                assume        esi:ptr MSG_QUEUE_ITEM
                invoke        lstrcpy,addr [esi].szSender,_lpszSender
                invoke        lstrcpy,addr [esi].szContent,_lpszContent
                inc        dwSequence
                mov        eax,dwSequence
                mov        [esi].dwMessageId,eax
                assume        esi:nothing
                invoke        LeaveCriticalSection,addr stCS
                popad
                ret

_InsertMsgQueue        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 从队列获取指定编号的消息
; -- 如果指定编号的消息已经被清除出消息队列,则返回编号最小的一条消息
;    当向连接速度过慢的客户端发消息的速度比不上消息被清除的速度,则中间
;    的消息等于被忽略,这样可以保证慢速链路不会影响快速链路
; -- 如果队列中的所有消息的编号都比指定编号小(意味着这些消息以前都被获取过)
;    那么不返回任何消息
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 入口:_dwMessageId = 需要获取的消息编号
;        _lpszSender = 用于返回消息中发送者字符串的缓冲区指针
;        _lpszSender = 用于返回消息中聊天内容字符串的缓冲区指针
; 返回:eax = 0(队列为空,或者队列中没有小于等于指定编号的消息)
;        eax <> 0(已经获取了一条消息,获取的消息编号返回到eax中)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_GetMsgFromQueue        proc        _dwMessageId,_lpszSender,_lpszContent
                        local        @dwReturn

                pushad
                invoke        EnterCriticalSection,addr stCS
                xor        eax,eax
                mov        @dwReturn,eax
                cmp        dwMsgCount,eax
                jz        _Ret

                mov        esi,offset stMsgQueue
                assume        esi:ptr MSG_QUEUE_ITEM
;********************************************************************
; esi 指向队列头部,所以这条消息的编号就是最小编号
; 最大编号=最小编号+队列长度-1
;********************************************************************
                mov        ecx,[esi].dwMessageId        ;ecx=队列中的最小消息编号
                mov        edx,dwMsgCount
                lea        edx,[edx+ecx-1]                ;edx=队列中的最大消息编号
;********************************************************************
; 如果指定编号 < 最小编号,则返回最小编号的消息
; 如果指定编号 > 最大编号,则不返回任何消息
;********************************************************************
                mov        eax,_dwMessageId
                cmp        eax,ecx
                jae        @F
                mov        eax,ecx
                @@:
                cmp        eax,edx
                ja        _Ret
                mov        @dwReturn,eax
;********************************************************************
; 要获取的消息在队列中的位置 = 指定消息编号-最小消息编号
;********************************************************************
                sub        eax,ecx
                mov        ecx,sizeof MSG_QUEUE_ITEM
                mul        ecx
                lea        esi,[esi+eax]
                invoke        lstrcpy,_lpszSender,addr [esi].szSender
                invoke        lstrcpy,_lpszContent,addr [esi].szContent
;********************************************************************
                assume        esi:nothing
_Ret:
                invoke        LeaveCriticalSection,addr stCS
                popad
                mov        eax,@dwReturn
                ret

_GetMsgFromQueue        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2007-11-27 19:13
0
雪    币: 290
活跃值: (11)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
7
看雪的 朋友真热情 呵呵  ,我才来的现在在学习,.,没什么时间上网 ,,1,1

尤其是scor   我吃饭了 ,,,
非常感谢!!
2007-11-27 19:17
0
雪    币: 297
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
8
用c sdk编程都很痛苦.
更何况asm...
2007-11-28 19:48
0
雪    币: 796
活跃值: (370)
能力值: ( LV9,RANK:380 )
在线值:
发帖
回帖
粉丝
9
我一直在痛苦中挣扎
2007-11-29 01:58
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
其实也没什么痛苦啦
2007-11-29 09:49
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
罗云彬的网站上有附书源码下载
http://211.90.241.130:22366/books/win32asm-2-src.rar
2007-11-29 19:11
0
游客
登录 | 注册 方可回帖
返回
//