⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.asm

📁 windows汇编语言程序设计 吴中平著 一书所附所有源代码。 该书重点讲解了Windows环境下汇编语言程序设计的基本原理及其实现过程
💻 ASM
字号:
include .\head.inc
client Struct 
   hsocket     HANDLE ?
   nickname    db 10 dup(?)
   nextlink    dd NULL
client endS

ModalDlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
GetSite PROTO  :DWORD,:DWORD,:DWORD
make_skt PROTO :dword
receive_pkt PROTO :dword,:dword
addchain  PROTO:dword
removechain PROTO:dword
AddNickName PROTO :dword,:dword
delay PROTO
GetTalker PROTO :dword,:dword

.const
IDD_SERVER               equ        102
IDC_EDIT                    equ        1000
IDC_STATICCOUNT    equ        1001
IDC_LIST                    equ        1004
UM_SOCK                   equ        WM_USER+100h
DEFAULT_PORT         equ        5150
.data
Prompt                db "TCP/IP",0
TitleName            db "服务器端",0
StartupError         db "套接字初始化错误!",0
SocketError         db "套接字创建错误!",0
SelectError          db "异步选择模式错误!",0
BindError            db "绑定错误!",0
AcceptError        db "拒绝客户请求!",0
pLinkHead          dd NULL
CountOL            dd 0
NickNameMark         db "@#@",0  
PrivateMark              db "@$@",0
DeleteMark               db "@!@",0
Crlf                          db 0dh,0ah,0
NickNameBuffer       db 20 dup (0)
say                          db "说:",0
.data?
hInstance	       HINSTANCE ?
hsocket            HANDLE    ?
hList                HANDLE    ?
hEdit                HANDLE    ?
hHeap              dd        ?
RecvBuffer      db 1024 dup (?)
DisplayBuffer   db 1200 dup (?)
talker               db 5 dup    (?)  
buffer              db 10 dup   (?)   
.code
start:
   invoke GetModuleHandle, NULL
   mov hInstance,eax
   invoke GetProcessHeap
   mov hHeap,eax        
   invoke DialogBoxParam,NULL,IDD_SERVER,NULL,addr ModalDlgProc,NULL
   invoke ExitProcess,eax

ModalDlgProc proc hWnd:dword,uMsg:dword,wParam:dword,lParam:dword
   local hnewsocket:HANDLE
   .if  uMsg==WM_INITDIALOG
      invoke GetDlgItem,hWnd,IDC_LIST
      mov hList,eax
      invoke GetDlgItem,hWnd,IDC_EDIT      
      mov hEdit,eax
      invoke make_skt,hWnd
   .elseif uMsg==WM_CLOSE
      .if  hsocket
         invoke closesocket,hsocket
      .endif
      invoke WSACleanup
      invoke EndDialog,hWnd,NULL
   .elseif  uMsg==UM_SOCK
      mov eax,lParam
      .if  ax==FD_ACCEPT
         invoke accept,wParam,0,0
         mov hnewsocket,eax   
         invoke WSAAsyncSelect,eax,hWnd,UM_SOCK,FD_READ or FD_CLOSE
         .if  eax==INVALID_SOCKET
            invoke closesocket,hsocket
            invoke MessageBox,hWnd,addr AcceptError,addr TitleName,MB_OK
            invoke SendMessage,hWnd,WM_CLOSE,0,0   
         .endif          
         invoke addchain,hnewsocket
         inc CountOL
         invoke SetDlgItemInt,hWnd,IDC_STATICCOUNT,CountOL,FALSE
      .elseif  ax==FD_READ
         invoke receive_pkt,wParam,hWnd
      .elseif  ax==FD_CLOSE
         dec CountOL
         invoke SetDlgItemInt,hWnd,IDC_STATICCOUNT,CountOL,FALSE
         invoke removechain,wParam
      .endif
   .elseif  uMsg==WM_COMMAND     
      mov eax,wParam       
   .else
      mov eax,FALSE
      ret
   .endif
   mov eax,TRUE
   ret
ModalDlgProc endp

make_skt proc hwnd:dword
   local wsaData:WSADATA
   local sin:sockaddr_in
   invoke WSAStartup,101h,addr wsaData
   .if  eax
      invoke MessageBox,hwnd,addr StartupError,addr TitleName,MB_OK
      invoke SendMessage,hwnd,WM_CLOSE,0,0
   .endif
   invoke socket ,AF_INET,SOCK_STREAM,0
   .if  eax==INVALID_SOCKET
      invoke MessageBox,hwnd,addr SocketError,addr TitleName,MB_OK
      invoke SendMessage,hwnd,WM_CLOSE,0,0   
   .endif
   mov hsocket,eax
   invoke WSAAsyncSelect,hsocket,hwnd,UM_SOCK,FD_ACCEPT 
   .if  eax==SOCKET_ERROR
      invoke WSAGetLastError
      .if  eax!=WSAEWOULDBLOCK
         invoke closesocket,hsocket
         invoke MessageBox,hwnd,addr SelectError,addr TitleName,MB_OK
         invoke SendMessage,hwnd,WM_CLOSE,0,0   
      .endif
   .endif
   invoke RtlZeroMemory,addr sin,sizeof sin
   invoke htons, DEFAULT_PORT
   mov sin.sin_port,ax
   mov sin.sin_family,AF_INET
   mov sin.sin_addr.S_un,INADDR_ANY
   invoke bind,hsocket,addr sin,sizeof sockaddr_in
   .if  eax
      invoke closesocket,hsocket
      invoke MessageBox,hwnd,addr BindError,addr TitleName,MB_OK
      invoke SendMessage,hwnd,WM_CLOSE,0,0
   .endif
   invoke listen,hsocket,8
   ret
make_skt endp

addchain proc uses edi hs:dword
   local ptemp:dword
   invoke HeapAlloc,hHeap,HEAP_ZERO_MEMORY,sizeof client
   mov ptemp,eax
   mov edi,eax
   assume edi:ptr client
   push hs
   pop [edi].hsocket
   .if  pLinkHead
      push pLinkHead
      pop [edi].nextlink
   .endif
   push ptemp
   pop pLinkHead
   assume edi:nothing 
   ret
addchain endp


removechain proc uses edi esi hs:dword
   local p:dword
   local len:dword
   mov NickNameBuffer,0
   mov edi,pLinkHead
   assume edi:ptr client
   mov eax,hs
   .if [edi].hsocket==eax
      push [edi].nextlink
      pop pLinkHead
      invoke SendMessage,hList,LB_FINDSTRING,0,addr [edi].nickname
      invoke SendMessage,hList,LB_DELETESTRING,eax,0
      invoke lstrcpy,addr NickNameBuffer,addr [edi].nickname
      invoke HeapFree,hHeap,HEAP_ZERO_MEMORY,edi
   .else
      .while edi
         mov eax,hs     
         .if  [edi].hsocket==eax
            push esi
            mov esi,p
            assume esi:ptr client
            .if  [esi].nextlink!=NULL
               push [edi].nextlink
               pop [esi].nextlink
               invoke SendMessage,hList,LB_FINDSTRING,0,addr [edi].nickname
               invoke SendMessage,hList,LB_DELETESTRING,eax,0
               invoke lstrcpy,addr NickNameBuffer,addr [edi].nickname
               invoke HeapFree,hHeap,HEAP_ZERO_MEMORY,edi 
               .break .if (TRUE)
            .else
               mov [esi].nextlink,NULL
            .endif
            assume esi:nothing
            pop esi
         .endif      
         mov p,edi
         push [edi].nextlink
         pop edi
      .endw  
   .endif  
   invoke lstrcat,addr NickNameBuffer,addr DeleteMark
   invoke lstrlen,addr NickNameBuffer
   mov len,eax
   mov edi,pLinkHead
   .while edi      
      invoke send,[edi].hsocket,addr NickNameBuffer,len,0
      push [edi].nextlink
      pop edi
   .endw 
   assume edi:nothing 
   ret
removechain endp

receive_pkt proc uses esi edi hs:dword,hwnd:HANDLE
   local len:dword
   mov talker,0
   mov DisplayBuffer,0
   invoke RtlZeroMemory,addr RecvBuffer,1024
   invoke recv ,hs,addr RecvBuffer,1024,0
   invoke InString,1,addr RecvBuffer,addr NickNameMark
   .if  eax
      invoke lstrlen,addr RecvBuffer
      mov len,eax
      mov edi,pLinkHead
      assume edi:ptr client
      .while  edi
         invoke send,[edi].hsocket,addr RecvBuffer,len,0;每个客户端的列表增加新登录的昵称。
         push [edi].nextlink
         pop edi       
      .endw
      mov edi,pLinkHead
      .while edi
         mov eax,hs
         .if  [edi].hsocket!=eax
            mov NickNameBuffer,0
            invoke lstrcpy,addr NickNameBuffer,addr [edi].nickname
            invoke lstrcat,addr NickNameBuffer,addr NickNameMark
            invoke lstrlen,addr NickNameBuffer
            invoke send,hs,addr NickNameBuffer,eax,0;新登录的客户端的列出在线昵称。
         .endif         
         push [edi].nextlink
         pop edi  
         invoke delay 
      .endw
      assume edi:nothing
      sub len,3
      lea esi,RecvBuffer
      add esi,len
      mov byte ptr [esi],0
      invoke AddNickName,hs,addr RecvBuffer;补加套接字对应的昵称
      ret
   .endif

   invoke GetTalker, hs,addr talker
   invoke lstrcat,addr DisplayBuffer,addr talker
   invoke lstrcat,addr DisplayBuffer,addr say
   invoke lstrcat,addr DisplayBuffer,addr RecvBuffer
   
   invoke InString,1,addr DisplayBuffer,addr PrivateMark
   .if  eax
      invoke GetSite,addr PrivateMark,addr DisplayBuffer,4
      dec eax
      lea esi,DisplayBuffer
      add esi,eax
      mov byte ptr[esi],0
      invoke lstrcat,addr DisplayBuffer,addr Crlf 
      invoke lstrlen,addr DisplayBuffer
      invoke send,hs,addr DisplayBuffer,eax,0
      mov edi,pLinkHead
      assume edi:ptr client
      .while edi
         mov buffer,0
         invoke lstrcat,addr buffer,addr PrivateMark
         invoke lstrcat,addr buffer,addr [edi].nickname
         invoke lstrlen,addr buffer
         invoke InString,eax,addr RecvBuffer,addr buffer
         .if  eax
            invoke lstrlen,addr DisplayBuffer
            invoke send,[edi].hsocket,addr DisplayBuffer,eax,0
         .endif
         push [edi].nextlink
         pop edi
      .endw  
      assume edi:nothing 
   .else
      invoke lstrcat,addr DisplayBuffer,addr Crlf 
      mov edi,pLinkHead
      assume edi:ptr client
      .while edi
         invoke lstrlen,addr DisplayBuffer
         invoke send,[edi].hsocket,addr DisplayBuffer,eax,0
         push [edi].nextlink
         pop edi
      .endw  
      assume edi:nothing 
   .endif
   invoke SendMessage,hEdit,EM_SETSEL,-1,-1
   invoke SendMessage,hEdit,EM_REPLACESEL,0,addr DisplayBuffer    
   ret
receive_pkt endp

GetTalker proc uses edi hs:dword,TalkerAddr:dword
   mov edi,pLinkHead
   assume edi:ptr client
   .while edi
      mov eax,hs
      .if [edi].hsocket==eax
         invoke lstrcpy,TalkerAddr,addr [edi].nickname
         .break .if(TRUE)
      .endif
      push [edi].nextlink
      pop edi  
   .endw
   assume edi:nothing
   ret
GetTalker endp


AddNickName proc hs:dword,NameAddr:dword
   invoke SendMessage,hList,LB_ADDSTRING,NULL,NameAddr
   mov edi,pLinkHead
   assume edi:ptr client
   .while   edi
      mov eax,hs
      .if  [edi].hsocket==eax
         invoke lstrcpy,addr [edi].nickname,NameAddr
         .break .if (TRUE)
      .endif
      push [edi].nextlink
      pop edi
   .endw
   assume edi:nothing
   ret
AddNickName endp

GetSite  proc  proc uses esi edi source:dword ,dest:dword,Count:dword
   local len:dword
   local buff[100]:byte
   mov esi,source
   mov edi,dest
   invoke lstrlen,edi
   mov len,eax
   .while  TRUE
   mov al,byte ptr [esi]
   mov ecx,len
   repne scasb
   .if  zero?
      dec edi
      invoke lstrcpyn,addr buff,edi,Count
      invoke lstrcmp,addr buff ,source
      .if  !eax
         sub edi,dest
         inc edi
         mov eax,edi
         .break .if (TRUE)
      .else
         inc edi
         invoke lstrlen,edi
         mov len,eax
      .endif
   .else
      mov eax,FALSE
      .break.if (TRUE)
   .endif
   .endw
   ret
GetSite endp

delay proc 
   pushad
   mov ecx,3fffffffh
again:
   loop again
   popad
   ret
delay endp
end start


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -