WIN32汇编语言教程:第16章 TCP/IP和网络通信 · 16.2 WinSock接口(1)
16.2.1 WinSock接口简介
Microsft为Win32环境下的网络编程提供了Windows Sockets接口(简称WinSock接口),正如Windows下的各种接口都是以API的形式出现的一样(如GDI),WinSock也是以一组API的方式提供的,从1991年推出1.0版开始,经过不断地完善后,WinSock接口现在已成为Windows下网络编程的标准。
WinSock接口是以BSD UNIX操作系统中流行的Socket接口为范例定义的,它包含了 UNIX Sockets接口中一系列的同名函数,但是Windows系统的运行方式和UNIX系统有显著的不同,为了和Windows系统相适应,WinSock接口在移植这些函数的同时对它们进行了改造,并针对Windows的消息驱动机制定义了一部分新的函数,所以使用WinSock接口的程序和UNIX网络通信程序的结构还是有很多的不同点的。
WinSock接口允许应用程序通过它来利用下层的网络通信协议进行通信。如图16.6所示,通过WinSock接口可以在TCP/IP模型的传输层上利用TCP或UDP协议进行通信,也可以在Internet层上直接使用IP协议,以便处理ICMP等数据包。
图16.6 WinSock接口
但WinSock接口并没有对应用层上的各种协议提供支持,所以应用程序无法通过WinSock接口提供的函数来实现HTTP,FTP与Telnet等协议,WinSock接口也不对绑定到TCP/IP协议上的NetBIOS协议提供支持,应用程序必须用另外的接口或者自己编程来实现这些高层协议。
大部分使用WinSock接口的程序主要是利用TCP协议来进行数据流通信或者利用UDP协议进行数据报通信,但是程序也可以通过WinSock接口直接使用IP协议来实现某些特殊功能,如实现ICMP与IGMP等Internet层上面的协议,或者用来发送非正常的数据包,比如在2000年2月份,雅虎、亚马逊和CNN等著名网站受到D.o.S(Denial of Service,拒绝服务)攻击而陷入瘫痪,D.o.S攻击程序制造了高流量的无用数据或反复发送畸形数据,以此引发服务器程序错误而大量占用系统资源,从而使主机处于假死状态甚至死机,D.o.S攻击程序使用的非正常的数据包就可以通过WinSock接口用IP协议实现。
1. WinSock接口中的套接字
为了使用WinSock接口进行通信,必须首先建立一个用来通信的对象,这个对象就称为套接字(Socket),套接字的定义是“通信的一端”,在通信的另一端必定有另一个套接字与之相对应以互相传递数据。使用WinSock接口进行通信的时候,第一个步骤就是建立一个套接字。
套接字的种类有很多种,最主要的两种是流套接字(stream socket)和数据报套接字(datagram socket)。流套接字使用传输层的TCP协议进行通信,所以它具有TCP协议所拥有的各种特征,比如它是面向连接的、稳定的,及数据包是顺序发送的等;而数据报套接字使用UDP协议进行通信,所以它的特征同样来自于UDP协议,如数据包可能丢失,可能重复,及可能不按顺序到达等。
另外,也存在其他一些不常用的套接字类型,如原始套接字(raw socket)、可靠信息分递套接字(rdm socket)和连续小分包套接字(seqpacket socket)等,其中值得一提的是原始套接字,使用这种套接字可以直接在Internet层上处理IP数据包的首部,所以可以用它来实现各种特殊的功能,如伪造发送者地址等。
一个套接字必须能与使用它的进程一一对应,所以对于流套接字和数据报套接字来说,IP地址和端口号是两个必不可少的参数,而对于原始套接字来说,由于它是在Internet层上工作的,在这里还没有开始使用端口号进行复用,所以它的有效参数只有IP地址。
有一部分介绍WinSock的书籍中讲到:“套接字的种类有两种——流套接字和数据报套接字”,这种说法是不确切的,因为正如上面介绍的,实际上还存在其他类型的套接字。
2. 套接字的工作模式
WinSock套接字的使用分为两种模式:阻塞模式和非阻塞模式。阻塞模式也称为同步模式,在这种模式下,WinSock函数直到全部操作完成后才返回。比如要接收数据包时,必须等到对方将数据包发送过来为止,调用WinSock函数的线程在这期间是被挂起的,所以程序看起来好像是停止响应了。显然,要以这种方式执行WinSock函数的话,几乎每个函数的使用都会违反“1/10秒规则”,所以必须考虑在不同的线程中执行每个WinSock函数,这显然是比较麻烦的。
在BSD UNIX中,套接字是以阻塞模式执行的,这对以命令行方式执行的UNIX程序来说并不是问题,但阻塞模式不是很适合于Windows下的消息驱动体系,所以WinSock为所有的函数提供了非阻塞模式的版本,非阻塞模式又称异步模式,在这种模式下,一个函数执行后会立即返回,即使是操作还没有全部完成,但是当函数最终完成操作的时候,WinSock接口会通过某种形式(如窗口消息)通知应用程序,显然这种方式非常适合于Windows下的消息驱动体系。
一般来说,WinSock接口强烈推荐程序员使用非阻塞模式进行通信编程,仅在绝对有必要的情况下才采用阻塞方式进行通信编程,因为非阻塞模式的操作能够更好地在Windows环境下进行。
16.2.2 WinSock编程概述
使用WinSock接口编程的一般步骤是:
(1)装入并初始化WinSock动态链接库。
(2)创建一个套接字。
(3)指定这个套接字的工作方式:使用阻塞模式还是非阻塞模式。
(4)如果使用TCP协议,则将套接字连接到对端主机的套接字(不使用TCP协议则不要这一步)。
(5)如果需要手工指定套接字使用的IP地址和端口号,那么将套接字绑定到指定的地址和端口(如果由系统自动分配地址和端口则不需要这一步)。
(6)通过套接字收发数据。
(7)关闭套接字。
(8)释放WinSock动态链接库。
1. WinSock库的初始化和释放
当前可以使用的WinSock接口动态链接库从版本上看有1.1版本和2.0版本两种,从位数分可以分为16位版本和32位版本,如图16.7所示,WinSock接口函数的代码主要包括在WS2_32.dll库文件中,这个库文件提供了对2.0版本WinSock接口的支持。但是在早期的Windows中,16位和32位的1.1版本的文件名分别是WinSock.dll和WSock32.dll,为了给使用这些库文件的程序提供兼容性支持,系统中仍然存在这两个文件,只不过在这两个文件中也是间接调用了WS2_32.dll文件而已。
为了使用WinSock接口,需要在源程序中包含对应的inc和lib文件,如果使用2.0版本,在源程序中必须包括WS2_32.inc和WS2_32.lib文件,如果要使用的是1.1版本的WinSock函数,那么既可以使用上面两个文件,也可以使用WSock32.inc和WSock32.lib文件。
图16.7 WinSock接口使用的动态链接库
上页:第16章 TCP/IP和网络通信 · 16.1 网络基础知识(3) 下页:第16章 TCP/IP和网络通信 · 16.2 WinSock接口(2)