win32汇编环境,网络编程入门之一
运行效果
;win32汇编环境,网络编程入门之一
;网络编程,我们先要认识几个概念,理解一点原理。太高深的研究不了,先理解一点应用的知识。这时候,应该假设你已经具备初步的使用WIN32汇编编程的能力的。
;网络编程,需要实战才能理解,在这几个教程里,我们先学会怎么访问某个网站。
;连接一部电脑,首先需要知道它的地址。这个叫IP。所以,我们首先要知道某个电脑的IP地址,服务器也是电脑
;比如我们访问一个网站,要知道它的IP是什么。大多数时候,我们知道的是网址。
;可以把网址转换成IP。在网上找个域名转IP的网站,把网址输进去,查一下,它就会告诉我们这个网站的IP是什么,现在就知道IP了
;然后,理解一下端口的概念
;端口是电脑的哪个门。每部电脑有很多门,有的门连接打印机,有的门连接话筒,有的门让别人访问它,这些门就是端口
;网站一般的端口是80或8080
;第三个概念是SOCKET,叫套接字,这是网络连接的机制。机制是什么东西?网络连接其实涉及很多东西,这个SOCKET把这些东西封装在一起,帮我们弄好了,我们输入一些参数就可以了。
;当然,也可以仔细剖开来研究,这可以写成整部的书。我们暂时不需要理解这么深,先学会简单的用就可以了。
;这里先弄个IP地址控件来,然后尝试一下基本的连接网络。
;IP地址控件不是读出来的地址就可以用的,我们需要转换一下它。至于怎么转换,我们在代码里面理解。
;下面为asm文件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
include kernel32.inc
include wsock32.inc ;需要添加的头文件,涉及socket
includelib user32.lib
includelib kernel32.lib
includelib wsock32.lib
; 自定义函数声明
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD ;对话框窗口函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN equ 1000 ;图标
IDC_IPA1 equ 1001
ID_BUTTON01 equ 41
TCP_PORT equ 80 ;端口
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
DlgName db "MyDialog",0
szErrIP db "无效的服务器IP地址!",0
szErrConnect db "无法连接到服务器!",0
szSucConnect db "可以连接到服务器!",0
szIP db "103.113.93.101",0 ;可派网站,也可以通过某个域名,在网站搜到这个域名的IP地址,放这里去尝试
szMsg db "提示",0
szFrm db "%d",0
.data?
hInstance HINSTANCE ?
hW_IP HWND ? ;IP地址控件的句柄
nGetIP dd ? ;存放从IP地址控件取得的值的指针
hSocket dd ?
szServer db 32 dup (?)
.const
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
invoke ExitProcess,eax
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL @stWsa:WSADATA
LOCAL @stSin:sockaddr_in
LOCAL @szBuffer[256]:byte
LOCAL @h01:byte,@h02:byte,@h03:byte,@h04:byte
.if uMsg == WM_INITDIALOG
invoke LoadIcon,hInstance,ICO_MAIN ;加载图标
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
invoke WSAStartup,101h,addr @stWsa ;这里的WSAStartup就是为了向操作系统说明,要使用哪个版本的socket。
invoke GetDlgItem,hWnd,IDC_IPA1 ;得到IP地址控件的句柄
mov hW_IP,eax
;IP地址控件内的值,是1个32位的数。其中每8位占一个值,最高的字节为IP地址的开头值,最低的字节为结束值。以下面的IP地址:103.113.93.101为例。
;先把低2个字节的值即103和113赋值,然后用 shl 指令往左移位16位,就是占了高2位字节的位置,再把IP地址的后面两个值给它加上
mov ah,103
mov al,113
shl eax,16
mov ah,93
mov al,101
invoke SendMessage,hW_IP,IPM_SETADDRESS,0,eax ;初始化设置控件里的IP地址值
.elseif uMsg == WM_COMMAND
mov ebx,wParam
.if bx == ID_BUTTON01
invoke RtlZeroMemory,addr @stSin,sizeof @stSin
invoke SendMessage,hW_IP,IPM_GETADDRESS,0,offset nGetIP ;取出IP地址控件里的值的指针,并把这个指针值放在nGetIP里
mov eax,dword ptr [nGetIP] ;得到IP地址控件里的IP值
mov @h04,al ;@h04其实是IP地址中的 101
mov @h03,ah ;@h03其实是IP地址中的 93
shr eax,16 ;往右移16位,即把高2字节的内容推到低2字节里去,而空出来的位置则置0,用这种方法得到原来高2字节里面每个字节的值
mov @h02,al ;@h02其实是IP地址中的 113
mov @h01,ah ;@h01其实是IP地址中的 103
;invoke wsprintf,addr @szBuffer,addr szFrm,@h01
;invoke MessageBox,hWnd,addr @szBuffer,NULL,MB_OK or MB_ICONINFORMATION
;开始创建IP字节序,其实就是把4个字节的顺序换换。这里需要的是网络字节序,它的顺序,可以看下面代码。
;相当于把原来的顺序 103.113.93.101 转换为 101.93.113.103,这是后面的 sockaddr_in 需要的格式
mov bl,@h03
mov bh,@h04
shl ebx,16
mov bl,@h01
mov bh,@h02
mov @stSin.sin_addr,ebx ;把IP地址转换成的网络字节序给 @stSin,
mov @stSin.sin_family,AF_INET ;指定是IPv4 的地址
invoke htons,TCP_PORT ;用htons函数把端口号进行转换,
mov @stSin.sin_port,ax ;将其低2字节值给sin_port成员
invoke socket,AF_INET,SOCK_STREAM,0 ;支持可靠的面向连接的字节流通信
mov hSocket,eax
; 连接到服务器
invoke connect,hSocket,addr @stSin,sizeof @stSin
.if eax == SOCKET_ERROR ;如果有错误,则返回SOCKET_ERROR
invoke MessageBox,hWnd,addr szErrConnect,NULL,MB_OK or MB_ICONSTOP
.elseif eax == 0 ;如果没有错,则返回0.没有错也不是马上连接上,它需要一点时间,所以可能会造成卡顿,这取决于网络。所以,我们一般把连接过程放在一个线程里面,这样就不会卡住主程序。
invoke MessageBox,hWnd,addr szSucConnect,NULL,MB_OK or MB_ICONINFORMATION
.endif
;至于怎么判断是否连接到了,不用急,在下一教程里我们再学。
.endif
.elseif uMsg == WM_CLOSE ;退出程序时记得清除套接字
.if ! hSocket ;如果socket创建失败,则清除它,否则先关闭,再清除
invoke WSACleanup
invoke EndDialog,hWnd,NULL
.else
invoke closesocket,hSocket
xor eax,eax
mov hSocket,eax
invoke WSACleanup
invoke EndDialog,hWnd,NULL
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
end start
;下面为rc文件内容
#include "resource.h" //提示缺少该文件,可以在资源里下载
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define ICO_MAIN 1000 //图标
#define IDC_IPA1 1001
#define ID_BUTTON01 41
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN ICON "Main.ico"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//定义对话框
MyDialog DIALOG 10, 10, 210, 40
STYLE DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "对话框程序模版"
FONT 11, "方正姚体"
BEGIN
CONTROL "输入IP地址:", -1, "Static", WS_CHILD | WS_VISIBLE, 10, 10, 50, 20
CONTROL "",IDC_IPA1,"SysIPAddress32",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,60,10,70,10
PUSHBUTTON "登录网站", ID_BUTTON01, 135,8,60,12
END