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

📄 016.txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 5 页
字号:

_SendData   proc

    local @szBuffer[1024]:byte

 

    invoke  GetDlgItemText,hWinMain,IDC_TEXT,\

        addr @szBuffer,sizeof @szBuffer

      invoke  lstrlen,addr @szBuffer

    .if   eax

      invoke  send,hSocket,addr @szBuffer,eax,0

    .if   eax ==  SOCKET_ERROR

      invoke  WSAGetLastError

    .if   eax == WSAEWOULDBLOCK

    invoke  EnableWindow,hWinOK,FALSE

        .endif

    .endif

    .endif

    invoke  SetDlgItemText,hWinMain,IDC_TEXT,NULL

    ret

 

_SendData   endp

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

; 主窗口程序

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

_ProcDlgMain     proc     uses ebx edi esi hWnd,wMsg,wParam,lParam

 


    local @stWsa:WSADATA

 

    mov   eax,wMsg

    .if   eax ==  WM_SOCKET

;********************************************************************

; 处理 Socket 消息

;********************************************************************

    mov   eax,lParam

    .if   ax == FD_READ

    invoke  _RecvData,wParam

    .elseif ax == FD_WRITE

    invoke  EnableWindow,hWinOK,TRUE

    .elseif ax == FD_CONNECT

      shr   eax,16

    .if   ax == NULL

      invoke  SetWindowText,hWinConnect,\

      addr szDisConnect

    invoke  EnableWindow,hWinConnect,TRUE

      invoke  EnableWindow,hWinServer,FALSE

    invoke  EnableWindow,hWinText,TRUE

      invoke  EnableWindow,hWinOK,TRUE

    invoke  SetFocus,hWinText

    .else

    invoke  _DisConnect

      invoke  MessageBox,hWinMain,\

      offset szErrConnect,NULL,\

      MB_OK or MB_ICONWARNING

      .endif

      .elseif ax == FD_CLOSE

      call     _DisConnect

    .endif

;********************************************************************

      .elseif eax ==  WM_COMMAND

    mov   eax,wParam

    .if   ax == IDOK

      invoke  _SendData

      .elseif ax == IDC_CONNECT

    .if   hSocket

      invoke  _DisConnect

      .else

    call     _Connect

      .endif

      .endif

;********************************************************************

    .elseif eax ==  WM_CLOSE

    invoke  _DisConnect

    invoke  WSACleanup

    invoke  EndDialog,hWinMain,NULL

;********************************************************************

    .elseif eax ==  WM_INITDIALOG

      push     hWnd

      pop   hWinMain

      invoke  GetDlgItem,hWnd,IDC_SERVER

    mov   hWinServer,eax

      invoke  GetDlgItem,hWnd,IDOK

      mov   hWinOK,eax

    invoke  GetDlgItem,hWnd,IDC_TEXT

      mov   hWinText,eax

      invoke  GetDlgItem,hWnd,IDC_CONNECT

      mov   hWinConnect,eax

    invoke  GetDlgItem,hWnd,IDC_INFO

    mov   hWinInfo,eax

      invoke  SetWindowText,hWinServer,addr szIP

      invoke  WSAStartup,101h,addr @stWsa

;********************************************************************

    .else

      mov   eax,FALSE

      ret

    .endif

    mov   eax,TRUE

      ret

 

_ProcDlgMain     endp

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

; 程序开始

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

start:

    invoke  GetModuleHandle,NULL

    invoke  DialogBoxParam,eax,DLG_MAIN,NULL,offset_ProcDlg Main,0

      invoke  ExitProcess,NULL

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

    end   start

在图16.8的模型中,已经了解了客户端程序大致的工作方式,但是到具体实现的时候,各种语句应该如何和Windows的消息驱动体系配合呢,上述源代码的结构看上去似乎比较松散,但是从图16.10中就可以看出它的工作流程。



图16.10  TCP客户端程序的常见结构

请读者结合图16.10中的数字序号来分析源代码,初始化WinSock库的WSAStartup函数被安排在窗口的初始化消息中(图中的①),当程序需要退出时,程序调用WSACleanup函数卸载WinSock库(图中的⑧)。

当用户要求连接时(比如例子中用户输入了IP地址并按下了“连接”按钮,见图16.10中的②),程序使用socket函数创建套接字,套接字的类型必须是流套接字,因为只有它是使用TCP协议的:

  invoke  socket,AF_INET,SOCK_STREAM,0

  mov hSocket,eax

  invoke  WSAAsyncSelect,hSocket,hWinMain,\

    WM_SOCKET,FD_CONNECT or FD_READ or FD_CLOSE or FD_WRITE

套接字创建以后,应该使用WSAAsyncSelect函数将通知消息以自定义的ID(例子中使用WM_SOCKET消息,它被预先定义为WM_USER+100)绑定到窗口过程中,这样就可以在适当的时候收到系统的通知消息,当收到消息的时候,lParam的低16位包括了通知码,高16位为出错信息,wParam参数指定了发生消息的套接字句柄。对于用于客户端的流套接字来说,在使用WSAAsyncSelect函数时必须包含FD_CONNECT,FD_READ,FD_WRITE和FD_CLOSE通知码。

完成这些事情后,接下来就可以使用connect函数去连接服务器了。

1. 连接到服务器

connect函数将一个流套接字连接到指定IP地址的指定端口上,它仅适用于流套接字,因为数据报套接字不是面向连接的。connect函数的用法是:

  invoke  connect,s,lpsockaddr,len

参数s指定用于连接的套接字句柄,lpsockaddr参数指向一个sockaddr_in结构,用来指定要连接到的服务器的IP地址和端口,这个结构在前面介绍的bind函数中已经使用过,len参数则指定sockaddr_in结构的长度。

当连接成功的时候,函数返回0,否则返回值是SOCKET_ERROR,但是当套接字工作在非阻塞模式时,函数返回的时候连接还没来得及完成,返回值肯定会是SOCKET_ERROR,但这并不意味着以后连接就不会成功,如果出错代码显示为WSAEWOULDBLOCK值,表示出错是因为操作尚未完成引起的,这时应该等待,否则才是真正的出错。

 


比如,例子程序中的

⌨️ 快捷键说明

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