📄 ciostart.asm
字号:
IOSKT_Start PROC uses edi esi lpTHIS:DWORD,_dwPortNum:DWORD,_lpServerWorkProc:DWORD
LOCAL @stInetAddr:sockaddr_in
LOCAL @stSysInfo :SYSTEM_INFO
LOCAL @dwLoops :DWORD
LOCAL @hThread :DWORD
LOCAL @dwThreadID:DWORD
LOCAL @hAccept :DWORD
LOCAL @hCompPort :DWORD
LOCAL @dwFlags :DWORD
LOCAL @RecvBytes :DWORD
SetObject edi,CLS_IOSKT
invoke RtlZeroMemory,addr @stInetAddr,sizeof @stInetAddr
mov esi,0
;===========================================================================
;1.创建完成端口
;===========================================================================
invoke CreateIoCompletionPort,INVALID_HANDLE_VALUE,NULL,0,0
mov [edi].m_hCompPort,eax
.if eax==NULL
invoke IOSKT_SetLastErr,lpTHIS,CTEXT("CreateIoCompletionPort 失败")
jmp @F
.endif
;===========================================================================
;2.检测系统信息
;===========================================================================
invoke RtlZeroMemory,addr @stSysInfo,sizeof @stSysInfo
invoke GetSystemInfo,addr @stSysInfo
;===========================================================================
;3.创建服务线程,数量为CPU*2
;===========================================================================
mov eax,2
mul @stSysInfo.dwNumberOfProcessors
mov @dwLoops,eax
xor ebx,ebx
.while ebx<@dwLoops
invoke CreateThread,NULL,NULL,_lpServerWorkProc,[edi].m_hCompPort,0,addr @dwThreadID
mov @hThread,eax
.if eax==NULL
invoke IOSKT_SetLastErr,lpTHIS,CTEXT("建立线程池线程 失败")
jmp @F
.endif
invoke CloseHandle,@hThread ;关闭句柄,能避免线程异常退出资源泄露
inc ebx
.endw
;===========================================================================
;4.创建监听Socket
;===========================================================================
invoke WSASocket,AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED
.if eax==INVALID_SOCKET
invoke IOSKT_SetLastErr,lpTHIS,CTEXT("WSAsocket 失败")
jmp @F
.endif
mov [edi].m_hListen,eax
mov @stInetAddr.sin_family,AF_INET
invoke htonl,INADDR_ANY
mov @stInetAddr.sin_addr.S_un.S_addr,eax
invoke htons,_dwPortNum
mov @stInetAddr.sin_port,ax
invoke bind,[edi].m_hListen,addr @stInetAddr,sizeof @stInetAddr
.if eax == SOCKET_ERROR
invoke IOSKT_SetLastErr,lpTHIS,CTEXT("bind端口 失败")
jmp @F
.endif
invoke listen,[edi].m_hListen,5 ;开始监听,指定最大同时连接数为5
.if eax==SOCKET_ERROR
invoke IOSKT_SetLastErr,lpTHIS,CTEXT("启动侦听listen 失败")
jmp @F
.endif
;===========================================================================
;5.开始接收从客户端来的连接
;===========================================================================
.while TRUE ;循环等待连接,然后由线程处理连接
invoke WSAAccept,[edi].m_hListen,NULL,NULL,NULL,0
mov @hAccept,eax
.if eax== SOCKET_ERROR
invoke IOSKT_SetLastErr,lpTHIS,CTEXT("接受客户端连接 失败")
jmp @F
.endif
;===========================================================================
;6.创建交换信息重叠结构关键项
;===========================================================================
invoke GlobalAlloc,GPTR,sizeof SOCKETCONTEXT
mov esi,eax
.if eax==NULL
invoke IOSKT_SetLastErr,lpTHIS,CTEXT("申请连接客户端数据交换内存 失败")
jmp @F
.endif
m2m (SOCKETCONTEXT ptr [esi]).hListen,[edi].m_hListen
;===========================================================================
;7.将客户端关联到完成端口
;===========================================================================
invoke CreateIoCompletionPort,@hAccept,[edi].m_hCompPort,esi,0
mov @hCompPort,eax
.if eax==NULL
invoke IOSKT_SetLastErr,lpTHIS,CTEXT("绑定到完成端口 失败")
jmp @F
.endif
;===========================================================================
;8.投递一个接收的IO覆盖指令
;===========================================================================
mov (SOCKETCONTEXT ptr [esi]).SendSize ,0 ;初始化缓冲区,并投递一个接收的准备
mov (SOCKETCONTEXT ptr [esi]).BytesSend,0
mov (SOCKETCONTEXT ptr [esi]).BytesRecv,0
mov (SOCKETCONTEXT ptr [esi]).dwIoFlag ,OP_READ ;参数信息
m2m (SOCKETCONTEXT ptr [esi]).hListen ,[edi].m_hListen
m2m (SOCKETCONTEXT ptr [esi]).hAccept ,@hAccept
m2m (SOCKETCONTEXT ptr [esi]).hCompPort,@hCompPort
m2m (SOCKETCONTEXT ptr [esi]).hClass ,lpTHIS
invoke RtlZeroMemory,addr (SOCKETCONTEXT ptr [esi]).Buffer,DATA_BUFSIZE ;缓冲区信息
invoke RtlZeroMemory,addr (SOCKETCONTEXT ptr [esi]).Overlapped,sizeof OVERLAPPED
mov (SOCKETCONTEXT ptr [esi]).DataBuf.len,DATA_BUFSIZE
lea eax,(SOCKETCONTEXT ptr [esi]).Buffer
mov (SOCKETCONTEXT ptr [esi]).DataBuf.buf,eax
;===========================================================================
mov @dwFlags,0
invoke WSARecv,(SOCKETCONTEXT ptr [esi]).hAccept, \
addr (SOCKETCONTEXT ptr [esi]).DataBuf,1, \
addr @RecvBytes, \
addr @dwFlags, \
addr (SOCKETCONTEXT ptr [esi]).Overlapped,NULL
.if eax==SOCKET_ERROR
invoke WSAGetLastError
.if eax!=ERROR_IO_PENDING
invoke IOSKT_SetLastErr,lpTHIS,CTEXT("CIoStart 服务器投递接收准备 失败")
jmp @F
.endif
.endif
.endw
@@:
ReleaseObject edi
ret
IOSKT_Start ENDP
IOSKT_Stop PROC uses edi lpTHIS:DWORD
SetObject edi,CLS_IOSKT
invoke shutdown,[edi].m_hListen,SD_BOTH
invoke closesocket,[edi].m_hListen
ReleaseObject edi
ret
IOSKT_Stop ENDP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -