Windows Socket 接口简介

  Windows Socket接口是Windows下网络编程的接口,在介绍Windows Socket接口之前,首先要简单介绍一下TCP/IP协议和描述网络系统架构的 OSI模型,以及TCP/IP模型 。
  一般来说, 网络系统的架构可以用开放系统互联模型(OSI模型)来描述,OSI模型分层的思想类似于Windows等操作系统的分层, 在Windows下, 应用程序位于最高层,应用程序通过API调用位于中间层次的系统子程序, 系统子程序再调用驱动程序, 驱动程序最终操作计算机的硬件, 各层次之间的隔离有利于层次间的分工协作, 只要每个层次都严格遵守边界协定, 那么它对于其他层次来说就可以看成是一个 “ 黑匣子 “,结果就是开发人员能够致力于本层次的开发和提高,而不必担心能否和其他层次合作。与之类似, OSI模型的体系结构分为7层, 其中网络应用程序位于最高层, 通过多个层次最终控制网络硬件所在的物理层来收发数据包。
  TCP/IP是Transmission Control Protocol/Internet Protocol (传输控制协议/网际协议)的缩写,它最初是在20世纪70年代初期由美国国防部出资为ARPA(美国高级研究项目局)开发的, 经过了多年以后,以TCP/IP 协议为基础构建的ARPA网逐步演变成了今天的 Internet。 TCP/IP网络的架构可以用TCP/IP模型来描述,这个模型和OSI模型极为相似,但是它将层次的划分减少到了4层,其每一层在功能上和OSI模型的一层或多层相对应,两种模型从工作原理上看并没有本质的区别。
  图16.1描述了OSI模型和TCP/IP模型各层次之间的对应关系,并例举了部分在各层次上工作的网络协议,读者可以在其中看到很多熟悉的名词,如Telnet,HfTP,TCP和UDP等。

图16.l OSI模型、TCP/IP模型的结构和WinSock接口的关系

  TCP/IP协议的核心协议运行于传输层和Internet层上, 主要包括TCP, UDP和IP协议, 其中TCP协议和UDP协议是以IP协议为基础而封装的,这两种协议提供了不同方式的数据通信服务。 在后面的16.2.3节中, 会对两种协议的区别做详细的介绍。如果说IP协议是道路, 那么下一层网络访问层的各种协议就相当于不同的铺路材料,而上一层的TCP和UDP 协议就相当于路上跑的不同类型的车辆; 再上层应用层的各种协议就相当于车上运送的丰富多彩的货物,它们都以TCP 和UDP 协议为载体来完成。比如,HTTP协议使用TCP协议传输网页, POP3协议使用TCP协议传输邮件, 而DNS协议使用UDP协议来传输域名和IP地址的翻译信息。

  Microsoft为Win32环境下的网络编程提供了Windows Sockets接口(简称WinSock 接口), 正如Windows下的各种接口都是以API的形式出现的一样(如GDI), Win_Sock也是以一组API的方式提供的,从1991年推出1.0版开始,经过不断地完善后,WinSock接口现在已成为Windows下网络编程的标准。

  由千网络协议最早是在UNIX 操作系统上实现的, 所以从可移植性考虑, WinSock 接口以BSD UNIX 操作系统中流行的Socket 接口为范例定义,它包含了UNIX Sockets 接口中一系列的同名函数,但是Windows 系统的运行方式和UNIX 系统有显著的不同,为了与Windows 系统相适应, WinSock 接在移植这些函数的同时对它们进行了改造, 并针对Windows 的消息驱动机制定义了一部分新的函数, 所以WinSock 接口函数实际上是UNIXSockets 接口函数的超集。

  如图16.1 所示, WinSock 接口提供的函数位千TCP/IP 模型中的传输层和Internet 层上面, 也就是说, 我们可以利用接口函数编写使用TCP 和UDP 协议的程序, 也可以编写直接使用1P 协议的程序,如使用ICMP 协议完成Ping 的功能,但WinSock 接口并没有对应用层上的各种协议提供支持,所以应用程序无法通过WinSock 接口提供的函数来实现HTTP 、FTP与Telnet 等协议, 应用程序必须用另外的接口或者自己编程来实现这些高层协议。

  与GDI 等接口类似, WinSock 接口也是通过几个动态链接库来提供的, 这些动态链接库从版本上分有1.1版本和2.0版本两种, 从位数分可以分为16 位版本和32 位版本, 如图16.2 所示, 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文件。

  在源文件中包含了对应的inc 文件和lib 文件后, 在使用其他WinSock 函数之前, 必须首先使用WSAStartup 函数来装入并初始化动态链接库, 否则对其他任何WinSock 函数的调用都不会成功, WSAStartup 函数只需要在程序开始的时候调用一次:

1 invoke WSAStartup,wVersionRequested,lpWSAData
2 .if eax
3 ;无法初始化WinSock库
4 .endif

图16.2 WinSock接口使用的动态链接库

  wVersionRequested 是一个16 位的参数, 用来指定动态链接库将支持哪个版本的WinSock 函数, 其中的低8位指定主版本号, 高8位用来指定副版本号, 假如要使用1.1版的, 可以在这里使用0101h, 假如需要使用2.0版本函数, 则可以将参数指定为0002h。

  lpWSAData 参数指向一个 WSADATA 结构, 用来返回动态链接库的详细信息, 结构的定义为:

WSADATA STRUCT
wVersion WORD ? ;库文件建议应用程序使用的版本
wHighVersion WORD ? ;库文件支持的最高WinSock 版本
szDescription BYTE WSADESCRIPTION_LEN + 1 dup (?);库描述字符串
szSystemStatus BYTE WSASYS_STATUS_LEN + 1 dup(?) ;系统状态字符串
iMaxSockets WORD ? ;同时支持的最大套接字数量
iMaxUdpDg WORD ? ; 2. 0 版中已废弃的字段
lpVendorinf o DWORD ? ; 2. 0 版中已废弃的字段
WSADATA ENDS

  szDescription 字段中返回的字符串一般是"WinSock 2.0" 之类的库描述串,szSystemStatus 字段中返回的是类似于“ Running" 一类的运行状态字符串。如果库装入成功, 函数将返回0, 否则将返回下面的出错代码:

1 • WSASYSNOTREADY--网络子系统未准备好。
2 • WSA VERNOTSUPPORTED--不支持指定的版本。
3 • WSAEINPROGRESS--另一个阻塞方式的WinSock 1.1 操作正在进行中。
4 • WSAEPROCLIM--WinSock 接口已经到达了所支持的最大任务数。
5 • WSAEFAULT--输入参数lpWSAData 指定的指针无效。

  不需要再使用WinSock 函数时, 比如, 在程序退出前, 必须使用WSACleanup 函数将库释放:

1 invoke WSACleanup

  WSACleanup 函数没有输入参数, 它将释放动态链接库并自动释放所有被创建的套接字等资源。如果函数执行成功将返回O, 否则将返回SOCKET ERROR。

 

posted @ 2020-12-05 21:20  YangARTuan  阅读(965)  评论(0编辑  收藏  举报