📄 窗口转发.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 + -