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

📄 窗口转发.asm

📁 采用窗口实现Socket消息转发的ASM代码
💻 ASM
字号:
.386
.model flat, stdcall
option casemap :none   ; case sensitive

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include\masm32\include\windows.inc
include\masm32\include\user32.inc
include\masm32\include\kernel32.inc
include\masm32\include\wsock32.inc

includelib   \masm32\lib\user32.lib
includelib   \masm32\lib\kernel32.lib
includelib   \masm32\lib\wsock32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DLG_MAIN   equ 2000
IDC_INFO   equ 2001
IDC_COUNT  equ 2002
WM_SOCKET  equ WM_USER + 100
DEBUG_FLAG equ 0

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
    dwPort        dd   9999
    dwMaxSocket   dd   32768   ;Socket最大容量
.data?
    hWinMain      dd   ?
    hSocket       dd   ?
    dwCount       dd   ?
    szReadBuffer  db   32768 dup (?)
    szBuffer      db   32768 dup (?)
    ddTableSource dd   32768 dup (?)
    ddTableTarget dd   32768 dup (?)
.const
    szErrBind     db   '无法绑定到TCP端口【%d】,请检查是否有其它程序在使用!',0dh,0ah,0
    szFormat      db   '【客户端#%08x】- %s',0dh,0ah,0

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code

_SetPort proc _ddPort:dword  ;设置客户端最大连接数
   local   @dwRet:dword
   
   mov    @dwRet,0
   .if _ddPort<=32768 
       mov    eax,_ddPort
       mov    dwPort,eax
   .else
       mov    @dwRet,1
   .endif
   mov    eax,@dwRet
   ret
_SetPort endp

_SetMaxSocket proc _ddMaxSocket:dword  ;设置客户端最大连接数
   local   @dwRet:dword
   
   mov    @dwRet,0
   .if _ddMaxSocket<=32768 
       mov    eax,_ddMaxSocket
       mov    dwMaxSocket,eax
   .else
       mov    @dwRet,1
   .endif
   mov    eax,@dwRet
   ret
_SetMaxSocket endp

_AddClient proc _hSocket:dword,_hwnd:dword            ;在客户端列表中加上一个 socket
    invoke WSAAsyncSelect,_hSocket,_hwnd,WM_SOCKET,FD_READ or FD_CLOSE  ;选择异步方式传输
    xor   ebx,ebx
    mov   esi,offset ddTableSource
    .while ebx < dwMaxSocket        ;为新客户端找一个空位,并将Socket句柄保存
       .if ! dword ptr [esi]
           push   _hSocket
           pop    [esi]
           mov    eax,0             ;返回成功
           ret
       .endif
       inc    ebx
       add    esi,4
    .endw
    invoke closesocket,_hSocket
    mov    eax,1                    ;返回失败
    ret
_AddClient endp

_RemoveClient proc _hSocket                                       ;从客户端列表中去掉一个 socket
    xor   ebx,ebx
    mov   esi,offset ddTableSource
    mov   edi,_hSocket
    .while ebx < dwMaxSocket                                      ;查找需要关闭的Socket
        .if [esi] == edi
            invoke closesocket,[esi]                              ;关闭指定的Socket
            mov    dword ptr [esi],0                              ;并清除指定位设置
            mov    eax,0                                          ;返回成功
            ret
        .endif
        inc    ebx
        add    esi,4
    .endw
    mov    eax,1                                                  ;返回失败
    ret
_RemoveClient endp

_RecvData proc _hSocket:dword,_szReadBuffer:dword,_dwSizeBuf:dword        ;处理接收到的TCP包
    local  @dwRecv

    mov    @dwRecv,0
    invoke RtlZeroMemory,_szReadBuffer,_dwSizeBuf                          ;初始化接收内存
    invoke recv,_hSocket,_szReadBuffer,_dwSizeBuf,NULL                     ;接收数据
    .if eax != SOCKET_ERROR                                          ;成功则转发
        mov    @dwRecv,eax
    .endif
    mov    eax,@dwRecv
    ret
_RecvData endp

_Initproc proc _dwPort:dword                                   ;初始化 Socket,绑定到服务TCP端口并监听
    local  @stWsa:WSADATA
    local  @stSin:sockaddr_in
    local  @dwRet:dword
    
    mov    @dwRet,0
    invoke WSAStartup,101h,addr @stWsa                         ;Socket初始化
    invoke socket,AF_INET,SOCK_STREAM,0                        ;启动流式Socket服务
    mov    hSocket,eax
    invoke WSAAsyncSelect,hSocket,hWinMain,WM_SOCKET,FD_ACCEPT ;选择异步通讯方式
    invoke RtlZeroMemory,addr @stSin,sizeof @stSin             ;初始化Socket结构体
    invoke htons,_dwPort                                       ;转换端口
    mov    @stSin.sin_port,ax
    mov    @stSin.sin_family,AF_INET
    mov    @stSin.sin_addr,INADDR_ANY
    invoke bind,hSocket,addr @stSin,sizeof @stSin              ;绑定窗口
    .if eax == SOCKET_ERROR                                    ;绑定不成功则返回失败
        mov    @dwRet,1
    .else
        invoke listen,hSocket,5                                ;帧听消息
    .endif
    mov    eax,@dwRet
    ret
_Initproc endp

; 主窗口程序
_ProcDlgMain   proc   uses ebx edi esi hWnd,wMsg,wParam,lParam
    local   @hSocket
    
    mov    @hSocket,0
    mov    eax,wMsg
    .if eax == WM_INITDIALOG              ;窗口初始化
        push   hWnd
        pop    hWinMain
        
        if DEBUG_FLAG
            invoke _SetPort,9998
            invoke wsprintf,addr szBuffer,addr szErrBind,dwPort
            invoke MessageBox,hWinMain,addr szBuffer,NULL,MB_OK or MB_ICONWARNING
        endif
        
        invoke _Initproc,dwPort
        .if eax == 1                      ;绑定失败报错
            invoke wsprintf,addr szBuffer,addr szErrBind,dwPort
            invoke MessageBox,hWinMain,addr szBuffer,NULL,MB_OK or MB_ICONWARNING
            invoke SendMessage,hWinMain,WM_CLOSE,0,0
        .endif
    .elseif eax == WM_SOCKET              ;SOCKET消息
        mov eax,lParam
        .if ax == FD_ACCEPT               ;客户端连接上来
            invoke accept,wParam,0,0
            invoke _AddClient,eax,hWinMain
            .if eax == 0 
                inc    dwCount
                invoke SetDlgItemInt,hWinMain,IDC_COUNT,dwCount,FALSE
            .endif
        .elseif ax == FD_READ             ;消息到来,需要读取
            mov    eax,wParam
            mov    @hSocket,eax
            invoke _RecvData,@hSocket,addr szReadBuffer,sizeof szReadBuffer ;接收包存放到缓冲区中
            .if eax > 0                                                   ;如果数据包大于零
                invoke wsprintf,addr szBuffer,addr szFormat,@hSocket,addr szReadBuffer
                invoke GetDlgItem,hWinMain,IDC_INFO
                mov    ebx,eax
                invoke GetWindowTextLength,ebx                                ;取文本框中消息宽
                invoke SendMessage,ebx,EM_SETSEL,eax,eax                      ;将光标移到最后
                invoke SendMessage,ebx,EM_REPLACESEL,FALSE,addr szBuffer      ;在光标处添加消息
                mov    esi,offset ddTableSource
                xor    ebx,ebx
                .while ebx < dwMaxSocket                                       ;按照客户端列表逐一发送
                    mov   edi,[esi]
                    .if   edi
                       invoke lstrlen,addr szBuffer
                       invoke send,edi,addr szBuffer,eax,0
                    .endif
                    add   esi,4
                    inc   ebx
                .endw
            .endif
        .elseif ax == FD_CLOSE            ;客户端关闭Socket
            invoke _RemoveClient,wParam
            .if eax == 0 
                dec    dwCount                                        ;连接个数减一
                invoke SetDlgItemInt,hWinMain,IDC_COUNT,dwCount,FALSE ;设置当前连接个数
            .endif
        .endif
    .elseif eax == WM_CLOSE               ;窗口退出时关闭全部连接
       invoke closesocket,hSocket
       xor    ebx,ebx
       mov    esi,offset ddTableSource
       cld
       .while ebx < dwMaxSocket
           lodsd
           .if eax
               invoke closesocket,eax
           .endif
           inc ebx
       .endw
       invoke WSACleanup
       invoke EndDialog,hWinMain,NULL ;关闭对话框
    .else
        mov eax,FALSE
        ret
    .endif
    mov eax,TRUE
    ret
_ProcDlgMain endp

; 程序开始
start:
    invoke   GetModuleHandle,NULL
    invoke   DialogBoxParam,eax,DLG_MAIN,NULL,offset _ProcDlgMain,0
    invoke   ExitProcess,NULL
end   start
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

⌨️ 快捷键说明

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