第5章网络程序设计基本知识_第1页
第5章网络程序设计基本知识_第2页
第5章网络程序设计基本知识_第3页
第5章网络程序设计基本知识_第4页
第5章网络程序设计基本知识_第5页
已阅读5页,还剩151页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第第6章章 网络程序设计基本知识网络程序设计基本知识 第第6章章 网络程序设计基本知识网络程序设计基本知识 6.1 6.1 网络应用程序的概念网络应用程序的概念6.2 TCP/IP6.2 TCP/IP应用程序工作模型与网络编程接口应用程序工作模型与网络编程接口6.3 6.3 套接口的概念及其编程原理套接口的概念及其编程原理6.4 Winsock API6.4 Winsock API基本函数基本函数套接口与连接的建立套接口与连接的建立6.5 Winsock API6.5 Winsock API基本函数基本函数数据传输数据传输6.6 Winsock API6.6 Winsock API基本函数基本

2、函数连接与套接口的关闭连接与套接口的关闭习题习题第第6章章 网络程序设计基本知识网络程序设计基本知识 6.1 网络应用程序的概念网络应用程序的概念6.1.1 什么是网络应用程序我们设计的应用程序可以简单地分为两种:一种程序不需要使用其他程序产生的数据并且其他程序也不使用它输出的数据;另一种程序需要与其他的应用程序进行数据交换才能完成其功能,也就是说程序之间存在通信问题。进程间通信的问题也可以分为两种:一种是在操作系统中论述的单机系统中进程间的通信问题,另一种一般是在不同系统的进程间通过网络通信协议进行的进程间的通信问题。第第6章章 网络程序设计基本知识网络程序设计基本知识 6.1.2 网络应用

3、程序的标识问题同一系统中不同进程间进行通信时,通过系统分配的进程号(Process ID)就可以惟一标识一个进程。也就是说,要通信的进程只要知道对方的进程号就可以进行通信。而网络情况下进程间的通信问题就要复杂得多,不能只简单地用进程号来标识不同的进程,因为各主机都独立地分配其进程号。 为了惟一地标识网络中通信的一个进程(即通信的某一方),就要使用一个如下的三元组:(本地协议,本地IP地址,本地端口号) 第第6章章 网络程序设计基本知识网络程序设计基本知识 这样一个三元组由于它只指定了通信时一条连接的半个部分,即通信的一方,因而称为半相关(Half-association)。如果要完整地表示网络

4、中进行通信的两个进程,那么就要使用一个如下结构的六元组:(本地协议,本地地址,本地端口号,远地协议,远地地址,远地端口号)在互联网中通信的两台主机在网络层都只能使用IP协议,但在网络层之上可以选择使用TCP协议或UDP协议,这样就可能得到以下4种类型的相关六元组: (本地TCP协议,本地IP地址,本地端口号,远程TCP协议,远程IP地址,远程端口号);第第6章章 网络程序设计基本知识网络程序设计基本知识 (本地UDP协议,本地IP地址,本地端口号,远程UDP协议,远程IP地址,远程端口号); (本地TCP协议,本地IP地址,本地端口号,远程UDP协议,远程IP地址,远程端口号); (本地UDP

5、协议,本地IP地址,本地端口号,远程TCP协议,远程IP地址,远程端口号)。如果通信的两端使用不同的协议(后两类六元组),根据前面我们所学的知识,由于TCP协议和UDP协议使用的协议格式大不相同,通信时双方在传输层不能相互识别对方送来的数据,也就不可能进行正常的通信,因此后两种情况是不存在的。第第6章章 网络程序设计基本知识网络程序设计基本知识 换句话说,通信的两个进程在端到端的传输层只能使用相同的协议,因此一个完整的网间通信就可以简化为用一个五元组来标识通信的两个进程:(协议,本地IP地址,本地端口号,远程IP地址,远程端口号)6.1.3 客户/服务器模型 1客户/服务器模型的特点客户/服务

6、器模型的通信方式从所具有的资源角度来说,有明显的非对称性。服务器拥有较多的资源,它具有运算能力强,数据存储容量大,通信速度快,系统的可靠性高等优点。相对来说,客户则拥有较少的资源,它在各方面的性能一般要比服务器差。 第第6章章 网络程序设计基本知识网络程序设计基本知识 客户/服务器模型在工作时,要求有一套客户机和服务器能共同识别的规则或约定,用来保证服务器方可以识别客户提出的请求是什么,客户方也能够解释收到的服务器应答。从本质上来说,这其实就是服务器方和客户方在通信中所使用的一套协议,它必须在通信的两端都被实现。根据实际情况,协议可能是对称的也可能是非对称的。在对称的协议中,每一方都有可能扮演

7、主从角色;在非对称协议中,一方被不可改变地认为是主机(服务器),而另一方则是从机(客户机)。 第第6章章 网络程序设计基本知识网络程序设计基本知识 2服务器的分类根据服务器提供服务方式的不同,服务器可以分为串行服务器和并发服务器。串行服务器只有一个进程用串行的方式对客户的请求提供服务;并发服务器可以为请求的每一个客户创建一个进程或线程,然后由对应的进程或线程给每一个客户提供服务。并发服务器又可以分为预先创建服务子进程(或线程)和按需创建服务子进程(或线程)两种方式。根据上面的分析,我们来总结一下客户/服务器模型的特点。对于服务器方来说: 服务进程一般在启动后就一直运行,以等待客户请求的到来,除

8、非服务被禁止或执行强迫终止服务程序。第第6章章 网络程序设计基本知识网络程序设计基本知识 服务器方进程使用的是众所周知的端口,否则客户无法知道提供服务的端口,也就不可能提出服务的请求。 服务器方通常拥有较多的资源(对称方式除外)。 服务器方进程可以并行处理多个客户的请求,当然可以同时处理的客户请求数目是有一定限制的。 服务器方在通信时属于被动的一方。对于客户方来说: 在需要服务时向服务器提出请求,请求的服务得到满足并完成处理任务后,就终止客户程序的执行。第第6章章 网络程序设计基本知识网络程序设计基本知识 使用向系统申请的临时端口与服务器方进程进行通信。 拥有相对较少的资源(对称方式除外)。

9、客户方在通信时属于主动的一方。第第6章章 网络程序设计基本知识网络程序设计基本知识 6.2 TCP/IP应用程序工作模型应用程序工作模型与网络编程接口与网络编程接口 6.2.1 TCP/IP应用程序工作模型使用TCP/IP协议的网络,其协议核心内容在层次结构的低三层,即网络接口层、IP层和传输层,而这三层的功能一般是由操作系统的内核来实现的。如图6-1所示的是两台主机的进程间通过网络编程接口进行通信的原理图。第第6章章 网络程序设计基本知识网络程序设计基本知识 客户应用程序网络应用程序编程接口TCP/IP 核心协议物理传输介质服务器应用程序网络应用程序编程接口TCP/IP 核心协议物理传输介质

10、图6-1 TCP/IP应用程序工作模型图 第第6章章 网络程序设计基本知识网络程序设计基本知识 图6-1所示的是使用TCP/IP协议网络的典型应用方式,即客户/服务器模式。通过图6-1用户还要明白一个问题,网络程序设计其实是使用系统提供的网络协议完成用户程序的功能,即在网络应用程序中使用网络协议提供的服务,而不是让用户去实现网络协议各层的功能。 第第6章章 网络程序设计基本知识网络程序设计基本知识 6.2.2 Windows Sockets简介1Windows Sockets的概念Windows Sockets是在Windows环境下使用的一套网络编程规范,常常简称为Winsock。2Wind

11、ows Sockets的来源Sockets本来是Unix操作系统下流行的一种网络编程接口(API),它是1983年在Berkeley(加州大学伯克利分校)4.2 BSD操作系统中被首先引入的,因此被称为“Berkeley Socket API”。 第第6章章 网络程序设计基本知识网络程序设计基本知识 3Windows Sockets的版本目前常用的Winsock有两个版本:一个是16位的Winsock 1.1,由动态链接库WINSOCK.DLL提供支持;另一个是32位的Winsock 2.2,由动态链接库WSOCK32.DLL提供支持。4Winsock API函数的分类在Winsock规范中把

12、Winsock API函数集分为与BSD Socket(用在Unix中)相兼容的基本函数、网络数据信息检索函数和Windows专用扩展函数三类。 第第6章章 网络程序设计基本知识网络程序设计基本知识 Winsock规范的核心内容是符合Berkeley Socket风格的库函数,但为了使程序员能充分利用Windows消息驱动机制进行编程,又定义开发了一组针对Windows的扩展库函数。 Windows Sockets规范中针对Windows的扩展部分,为应用程序开发者提供了开发Windows应用软件的功能,它有利于程序员写出更加稳定并且更加高效的程序。另外,除了WSAStartup()和WSAC

13、leanup()两个函数外(在6.5节介绍),其他Windows扩展函数的使用不是强制性的。第第6章章 网络程序设计基本知识网络程序设计基本知识 5Windows Sockets对多线程的支持Windows Sockets支持多线程的Windows进程。一个进程可以包含一个或多个同时执行的线程(在Windows 3.1非多线程版本中,一个任务对应了一个仅具有单个线程的进程)。6.2.3 Windows Sockets规范的目标及几个相关的概念1Windows Sockets规范的目标Windows Sockets规范的目标有两个:一是给网络应用程序的开发者提供一套简单的网络编程API;二是让各

14、家网络软件供应商能够根据这套规范建立各自的符合Windows Sockets标准的实现和应用程序。第第6章章 网络程序设计基本知识网络程序设计基本知识 此外,在一个特定Windows版本的基础上,Windows Sockets也定义了一个二进制接口(ABI),以此来保证应用Windows Sockets API的应用程序能够在任何网络软件供应商的符合Windows Sockets协议的实现上工作。2Windows Sockets兼容和Windows Sockets提供者遵守Windows Sockets规范的网络软件称之为是Windows Sockets兼容的,而Windows Sockets

15、兼容实现的提供者称之为Windows Sockets提供者。一个网络软件供应商必须百分之百地实现Windows Sockets规范才能做到与Windows Sockets兼容。 第第6章章 网络程序设计基本知识网络程序设计基本知识 3Windows Sockets应用程序任何能够与Windows Sockets兼容实现协同工作的应用程序都被认为是具有Windows Sockets接口的,称这种应用程序为Windows Sockets应用程序。应用程序通过调用Windows Sockets的API实现它们之间的相互通信。Windows Sockets又利用下层的网络通信协议功能和操作系统调用来实

16、现实际的通信工作。第第6章章 网络程序设计基本知识网络程序设计基本知识 6.3 套接口的概念及其编程原理6.3.1 套接口(Socket) Windows Sockets API依靠套接口(Socket)进行通信。套接口可以看成是两个网络应用程序进行通信时,各自通信连接中的一个端点。通信时,其中的一个网络应用程序将要传输的一段信息写入它所在主机的Socket中,该Socket通过网络接口卡(NIC)的传输介质将这段信息发送到另一台主机的Socket中,使这段信息能传送到其他程序中,如图6-2所示。 第第6章章 网络程序设计基本知识网络程序设计基本知识 程序A基于TCP/IP的网络程序B网络管理

17、软件网络接口卡(NIC)主机A主机B套接口套接口图6-2 套接口示意图 第第6章章 网络程序设计基本知识网络程序设计基本知识 现在我们根据图6-2来分析一下使用套接口进行通信的过程。当主机A(Host A)上的网络应用程序(Program A)要发送数据时,通过调用数据发送函数首先将要发送的一段信息写入其Socket中,Socket中的内容通过主机A的网络管理软件由主机A的网络接口卡发送到主机B(Host B),主机B的网络接口卡接收到这段信息后,再传送给主机B的网络管理软件,网络管理软件将这段信息保存在主机B的Socket中,然后程序B(Program B)才能在Socket中读取并使用这段

18、信息。第第6章章 网络程序设计基本知识网络程序设计基本知识 从以上的通信过程可以看出,如果不考虑通信过程中的网络接口卡和传输介质等,则网络通信的过程就是由数据的发送者将要发送的信息写入一个套接口,再通过中间环节将信息传输到接收端的套接口中,然后就可以由接收端的应用程序将信息从套接口中取出。因此,两个应用程序之间的数据传输要通过套接口来完成。在学习了后面更多的内容后我们将会体会到,套接口的本质是通信过程中所要使用的一些缓冲区及一些相关的数据结构。第第6章章 网络程序设计基本知识网络程序设计基本知识 6.3.2 套接口的分类为了满足不同的通信程序对通信质量和性能的要求,一般的网络系统提供了三种不同

19、类型的套接口,以供用户在设计网络应用程序时根据不同的要求来选择。这三种套接口分别是:(1) 流式套接口(SOCK_STREAM) 。(2) 数据报套接口(SOCK_DGRAM) 。(3) 原始套接口(SOCK_RAW) 。第第6章章 网络程序设计基本知识网络程序设计基本知识 6.3.3 套接口编程原理该过程可以分为以下几个阶段:(1) 电信局必须要有一个电话总机,相当于套接口通信机制中提供服务的服务器。在Socket中通过调用socket()函数来开启一个服务,即创建一个提供服务的套接口。(2) 电信局必须给电话总机分配一个号码(如114,即查号服务的号码是114),以便用户通过拨该号码得到电

20、话服务,同时接入该电信局的用户必须知道该总机的号码。 第第6章章 网络程序设计基本知识网络程序设计基本知识 (3) 电信局114查号台下会开设一些自动服务的分机,但是它们的数量是有限的。总机开通后就一直在监听(listen)用户的拨号,用户拨打114时,可能拨通,得到服务;也可能拨不通,就会听到忙音。同样,我们在建立一个Socket服务时,也会调用listen()函数来监听客户的请求。(4) 对于用户来说,如果知道电信局的查号号码,在想得到查号服务时就可以拨打114,请求得到电信局的服务,这相当于在客户端要进行的操作。 第第6章章 网络程序设计基本知识网络程序设计基本知识 (5) 电信局的总机

21、接受了某用户拨打的电话后,负责把用户与一个分机连通,而总机本身则又回到等待状态,等待其他客户的请求。 (6) 服务完成后,挂上电话,线路断开,一次服务过程结束,否则该线路将一直被占用,浪费了通信资源。在服务器和客户之间,最后也要使用closesocket()函数关闭套接口,释放该套接口上的有关资源,这可以由通信的任何一方或双方同时提出。第第6章章 网络程序设计基本知识网络程序设计基本知识 6.3.4 Winsock套接口编程时对错误的处理机制 用户编写网络应用程序时,出现错误是不可避免的,因此对错误的检查和控制至关重要,一个好的或者说成功的Winsock应用程序应该尽可能地检测和处理各种错误。

22、对Winsock函数来说,返回错误是很常见的。与大多数系统调用类似,Winsock函数发生的错误也有两种。不成功的Winsock函数调用返回的最常见的值是宏定义SOCKET_ERROR,在Winsock的头文件中(如Winsock2.h),它的数值是1。 第第6章章 网络程序设计基本知识网络程序设计基本知识 该函数的使用非常简单,格式如下:int WSAGetLastError ( void );这是一个无参函数,调用时返回最新发生的网络错误代码。调用该函数时要注意,当一特定的Windows Sockets API函数指出一个错误已经发生时,就应该调用本函数来获得对应的错误代码。WSAGetL

23、astError()函数返回的这些错误都已预定义成常量值,根据Winsock版本的不同,这些值的声明不在Winsock1.h中,就在Winsock2.h中。这两个头文件的惟一差别是Winsock2.h中包含的错误代码(针对Winsock 2而引入的一些新的API函数)更多。为各种错误代码定义的常量(带有#定义的宏)一般都以WSAE开头。 第第6章章 网络程序设计基本知识网络程序设计基本知识 6.3.5 网络字节顺序不同的主机对字节值的存储顺序不同。在存储由多个字节组成的一个字时,有的计算机在起始地址处存放整数的低序号字节,这种存储格式叫“小序在前”(Little-endian);而有的计算机在

24、起始地址处存放整数的高序号字节,这种存储格式叫 “大序在前”(Big-endian)。计算机究竟采用那种字节存储顺序由各自的设计决定,如Windows系列的操作系统使用的是小序在前的存储方式,而Sun OS和Solaris等采用的大序在前的存储方式。 第第6章章 网络程序设计基本知识网络程序设计基本知识 在计算机中,TCP/IP协议使用的16位整数(如端口号)和32位整数(如IP地址)是按计算机各自的“主机字节”(Host-byte)来表示的。在网络中,为了保证数据的正确性,网络通信协议中必须指定网络字节顺序。如果在网络中使用IP地址和端口号,按“互联网联网标准”的要求,指定的多字节值必须用“

25、大序在前”的形式来表示,一般称之为“网络字节”(Network-byte)顺序。 第第6章章 网络程序设计基本知识网络程序设计基本知识 在Winsock中,有一系列的函数可用于多字节数的转换,把它们从主机字节顺序转换成网络字节顺序,反之亦然。下面4个API函数便将一个数从主机字节顺序转换成网络字节顺序: htonl():参数是主机字节顺序的一个4字节数,函数返回网络字节顺序的数; WSAHtonl():参数是主机字节顺序的一个4字节数,函数返回网络字节顺序的数; htons():参数是主机字节顺序的一个2字节数,函数返回网络字节顺序的数; WSAHtons():参数是主机字节顺序的一个2字节数

26、,函数返回网络字节顺序的数。第第6章章 网络程序设计基本知识网络程序设计基本知识 6.4 Winsock API基本函数套接口与连接的建立6.4.1 打开WinsockWSAStartup()应用程序或DLL只能在一次成功的WSAStartup()调用之后才能进一步调用其他的Windows Sockets API函数。1函数格式WSAStartup()函数的格式如下:int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);第第6章章 网络程序设计基本知识网络程序设计基本知识 2函数参数说明wVersionRequested:此参数是

27、一个WORD型(双字节型)数值,它指定准备在应用程序中要使用的Winsock库的版本号。其中,用高位字节指定副版本,用低位字节指定主版本。就目前的Win32平台而言,Winsock 2库的最新版本是2.2(Win95为Winsock 1.1)。如果需要加载Winsock 2.2版,指 定 此 参 数 的 值 为 0 x 0 2 0 2 ; 也 可 使 用 宏MAKEWORD(X,Y),其中X为高位字节,Y为低位字节,如MAKEWORD(2,2)。lpWSAData:此参数是一个指向WSADATA结构的指针。当该函数被调用时,它返回关于Windows Sockets实现的详细信息,该结构的定义如

28、下: 第第6章章 网络程序设计基本知识网络程序设计基本知识 typedef struct WSADataWORD wVersion;WORD wHighVersion;Char szDescriptionWSADESCRIPTION_LEN+1;Char szSystemStatusWSASYS_STATUS_LEN+1;unsigned short iMaxSockets;unsigned short iMaxUdpDg;char FAR * lpVendorInfo; WSADATA,FAR *LPWSADATA;第第6章章 网络程序设计基本知识网络程序设计基本知识 各字段的含义说明如下:

29、 wVersion:调用者希望使用的Winsock版本号;wHighVersion:加载的Winsock库所支持的最高Winsock版本,通常和wVersion的值相同;szDescription:系统加载的Winsock库的说明字符串,如“Winsock 2.0”;szSystemStatus:系统状态或配置信息的说明字符串;iMaxSockets:套接口的最大编号(该字段被Winsock 2或其后的版本忽略);第第6章章 网络程序设计基本知识网络程序设计基本知识 iMaxUdpDg:UDP数据报的最大容量(该字段被Winsock 2或其后的版本忽略);lpVendorInfo:厂商专有信息

30、(该字段被Winsock 2或其后的版本忽略)。3函数返回信息WSAStartup()函数的返回值是一个整数,如果调用成功则返回0。 WSAStartup()函数调用不成功时返回如下的错误信息:WSASYSNOTREADY:在Winsock的头文件Winsock2.h中,该错误代码定义的数值为10091,它表明加载的Winsock DLL不存在或底层的网络子系统无法使用。第第6章章 网络程序设计基本知识网络程序设计基本知识 WSAVERNOTSUPPORTED:该代码的数值为10092,所需的Windows Sockets API的版本未由特定的Windows Sockets实现提供。如果由w

31、Version返回的版本用户不能接受,则要调用WSACleanup()函数清除对Winsock的加载。 WSAEINVAL:该代码的数值为10022,说明应用程序指出的Windows Sockets版本不能被该Winsock DLL的实现所支持。 WSAEINPROGRESS:该代码的数值为10036,说明一个阻塞的Winsock调用正在进行中。 WSAEPROCLIM:该代码的数值为10067,说明已经达到了Windows Sockets实现所支持的任务数量的极限。 第第6章章 网络程序设计基本知识网络程序设计基本知识 WSAEFAULT:该代码数值为10014,说明lpWSAData参数是

32、一个无效的指针。注意:在这里为了便于大家理解错误代码,列出了给错误代码定义的数值。以后为了节省篇幅,不再列出错误代码的数值。如果要查询对应错误代码对应的数值,可以在Winsock的头文件Winsock.h或Winsock2.h中去查找。第第6章章 网络程序设计基本知识网络程序设计基本知识 4函数使用说明如果用户在没有正确加载Winsock DLL的情况下使用了其 他 的 Wi n s o c k A P I 函 数 , 则 被 调 用 的 函 数 返 回WSANOTINITIALISED错误信息,代码为10093。该函数在程序中的基本使用方法如下:#include/其他代码WORD wVers

33、ionRequested;WSADATA wsaData;wVersionRequested=MAKEWORD(2,2);if(WSAStartup(wVersionRequested,&wasData)!=0)第第6章章 网络程序设计基本知识网络程序设计基本知识 /Winsock初始化错误/输出Winsock初始化错误提示信息,如“WSAStartup failed”return;/下面可以用两种方法中的任一种进行版本号匹配的检查/if(LOBYTE(wsaData.wVersion)!=2|HIBYTE(wsaData.wVersion)!=0)if(wsaData.wVersio

34、n!=wVersionRequested)第第6章章 网络程序设计基本知识网络程序设计基本知识 /Winsock版本号不匹配/输出Winsock版本号不匹配的错误提示信息;WSACleanup();return;/说明Winsock DLL的加载正确,可以执行以下的其他代码/其他程序代码结束对Winsock DLL库的使用时,一定要调用WSACleanup()函数卸载所加载的库。第第6章章 网络程序设计基本知识网络程序设计基本知识 6.4.2 创建套接口socket()或WSASocket()应用程序在使用套接口通信前,必须要拥有一个套接口。使用socket()或WSASocket()函数来给

35、应用程序创建一个套接口。 1函数格式 在Winsock 1中提供的创建套接口函数的格式如下: SOCKET socket( int af, int type, int protocol );第第6章章 网络程序设计基本知识网络程序设计基本知识 在Winsock 2中提供的该函数的扩展格式如下: SOCKET WSASocket( int af, int type, int protocol, LPWSAPROTOCOL_INFO lpProtocolInfo, Group g, int iFlags);第第6章章 网络程序设计基本知识网络程序设计基本知识 2函数参数说明以上两种格式中,前面三个

36、参数的含义是一样的,说明如下: af:该参数说明套接口要使用的协议地址族,地址族与协议族的含义相同。如果想建立一个UDP或TCP套接口,只能用常量AF_INET表示使用互联网协议(IP)地址。当然,Winsock 2还支持其他的协议,但一般在程序中很少使用。type:该参数描述套接口的协议类型。当第一个参数af是AF_INET时,它只能使用SOCK_STREAM、SOCK_DGRAM或SOCK_RAW三个协议类型中的任一个,分别表示要创建的是流式套接口、数据报套接口或原始套接口。第第6章章 网络程序设计基本知识网络程序设计基本知识 protocol:该参数说明该套接口使用的特定协议。当协议地址

37、族af和协议类型type已经确定后,协议字段可以使用的值是限定的,如表6-1所示。如果调用者不希望特别指定所使用的协议,可以将此参数设置为0,系统就根据前两个参数的值自动确定一个协议字段的取值。以上三个参数就可以确定一个套接口,它们之间的对应关系可以用表6-1表示。 第第6章章 网络程序设计基本知识网络程序设计基本知识 表6-1 套接口参数 协议 地址族 套接口类型 套接口类型使用的值 协议字段 TCP SOCK_STREAM IPPROTO_TCP UDP SOCK_DGRAM IPPROTO_UDP 互联网协议(IP) AF_INET Raw sockets SOCK_RAW IPPROT

38、O_RAW IPPROTO_ICMP 第第6章章 网络程序设计基本知识网络程序设计基本知识 系统可以根据这三个参数建立一个套接口,并给它分配相应的资源,同时返回一个整型套接口号。因此,socket()函数调用实际上指定了相关五元组中的“协议”这一元。使用Winsock 2时,一般可以先用WSAEnumProtocols()函数(该函数在第8章介绍),以获得系统所安装协议的相关信息。当然对现在的绝大部分用户来说,直接使用AF_INET(IP协议族)就可以了,因为几乎所有的协议实现系统都支持IP协议族。但要编写通用性好的应用程序时,最好还是先使用WSAEnumProtocols()函数查询一下系统

39、安装的协议。第第6章章 网络程序设计基本知识网络程序设计基本知识 在Winsock 2提供的扩展格式中,增加了三个参数,其含义说明如下(因为常用的是格式1,所以这三个参数只需了解其大概的含义):lpProtocolInfo:一个指向WSAPROTOCOL_INFO结构的指针,该结构定义所创建套接口的特性。如果本参数不指向空(NULL),则前三个参数(af, type, protocol)被忽略,系统就根据该结构中三个字段的值确定套接口类型。 g:套接口组的描述字。组参数始终为0,因为目前尚无可支持套接口组的Winsock版本。第第6章章 网络程序设计基本知识网络程序设计基本知识 iFlags:

40、套接口属性描述。iFlags可用参数如下:WSA_FLAG_OVERLAPPEDWSA_FLAG_MULTIPOINT_C_ROOTWSA_FLAG_MULTIPOINT_C_LEAFWSA_FLAG_MULTIPOINT_C_ROOFWSA_FLAG_MULTIPOINT_D_LEAF第第6章章 网络程序设计基本知识网络程序设计基本知识 第一个标志WSA_FLAG_OVERLAPPED用于指定这个套接口具备重叠I/O(是适用于Winsock的通信模式之一)的特性。调 用 s o c k e t ( ) 建 立 一 个 套 接 字 时 ,WSA_FLAG_OVERLAPPED便是默认设置。一般

41、说来,在使用WSASocket时,最好始终保持设定该标志。后面4个标志用于处理多播套接口。3函数返回信息该函数调用成功后,返回新创建的套接口号,它被定义成是一个无符号的整型数据。函数调用错误时返回INVALID_SOCKET,应用程序可进一步调用WSAGetLastError()函数来获取相应的错误代码。可能获得的错误代码说明如下:第第6章章 网络程序设计基本知识网络程序设计基本知识 WSANOTINITIALISED:在调用本API之前应成功调用WSAStartup();WSAENETDOWN:网络子系统失效;WSAEAFNOSUPPORT:不支持指定的地址族;WSAEINPROGRESS:

42、一个阻塞的Winsock调用正在进行中,或者服务提供者仍在处理一个回调函数;WSAEMFILE:无可用的套接口描述字;WSAENOBUFS:无可用的缓冲区空间,套接口无法创建;第第6章章 网络程序设计基本知识网络程序设计基本知识 WSAEPROTONOSUPPORT:不支持指定的协议; WSAEPROTOTYPE:指定的协议对于本套接口类型错误; WSAESOCKTNOSUPPORT:本地址族不支持指定的套接口类型; WSAEINVAL:g参数非法。4函数使用说明第第6章章 网络程序设计基本知识网络程序设计基本知识 要创建一个流套接口时,可以使用下列三种格式之一:SOCKET sockid=s

43、ocket(AF_INET,SOCK_STREAM,IPPROTO_TCP);SOCKET sockid=WSASocket(AF_INET,SOCK_STREAM,0);SOCKET sockid=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);第第6章章 网络程序设计基本知识网络程序设计基本知识 要创建一个数据报套接口时,其格式如下(为节省篇幅,两种套接口的创建只给出了一种格式):SOCKET sockid=socket(AF_INET,SOCK_GDRAM,IPPROTO_UDP);要创建一个原始套接口时,其格式如下

44、:SOCKET sockid=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); 第第6章章 网络程序设计基本知识网络程序设计基本知识 6.4.3 指定本地地址bind()当用socket()创建了一个套接口后,该套接口还是不能直接使用,因为它只存在于一个名字空间(地址族)中,也就是说它只确定了通信所希望使用的服务类型,并没有与该主机上提供服务的某端口联系在一起,这样的套接口可以叫未命名的套接口。bind()函数通过给一个未命名的套接口分配一个本地名字来为套接口建立本地捆绑,即把一个套接口与一个主机地址和端口号联系起来。本函数适用于数据报或流类套接口。第第6章章 网络

45、程序设计基本知识网络程序设计基本知识 1函数格式bind()函数的格式如下:int bind(SOCKET s,const struct sockaddr FAR* name,int namelen);第第6章章 网络程序设计基本知识网络程序设计基本知识 2函数参数说明bind()函数中各参数的说明如下: s:标识一未绑定套接口的描述字,它是socket()函数调用成功时返回的值。 name:是一个与指定协议有关的地址结构指针,它指向的值是赋予套接口的地址信息。在Winsock中使用sockaddr_in结构指定IP地址和端口信息,它的定义如下:struct sockaddr_inshort

46、sin_family;u_short sin_port;struct in_addrsin_addr;charsin_zero8; 第第6章章 网络程序设计基本知识网络程序设计基本知识 其中,sin_family字段必须为AF_INET,以告诉Winsock所使用的是IP地址族;sin_port是以网络字节顺序表示的16位端口号;sin_addr是以网络字节顺序表示的32位IP地址;sin_zero字段不用,一般用0填充,在程序中通常是使用sockaddr_in之前将整个结构置0。 namelen:bind()函数的这个参数指地址参数(name)的长度。 第第6章章 网络程序设计基本知识网络程

47、序设计基本知识 3函数返回信息如果调用没有错误发生,则bind()返回0,否则将返回SOCKET_ERROR,应用程序可进一步通过WSAGetLastError()函数来获取相应的错误代码。下面是可能获取的错误代码: WSANOTINITIALISED:在使用此API之前应首先成功调用WSAStartup(); WSAENETDOWN:Windows套接口实现检测到网络子系统失效;第第6章章 网络程序设计基本知识网络程序设计基本知识 WSAEADDRINUSE:所指定的端口已在使用中; WSAEFAULT:namelen参数太小(小于sockaddr结构的大小); WSAEINPROGRESS

48、:一个阻塞的Windows套接口调用正在运行中; WSAEAFNOSUPPORT:本协议不支持所指定的地址族; WSAEINVAL:该套接口已与一个地址捆绑; WSAENOBUFS:无足够可用缓冲区,连接过多; WSAENOTSOCK:指定的描述字不是一个套接口。第第6章章 网络程序设计基本知识网络程序设计基本知识 4函数使用说明各种IP地址和端口的设置可用表6-2表示。 第第6章章 网络程序设计基本知识网络程序设计基本知识 表6-2 IP地址和端口的几种设置方式IP 地址参数 端口参数 含 义 bind( )使用说明 INADDR_ANY 非 0 IP 地址由系统内核自动指定 可用于只有一个

49、 IP 地址的服务器端 bind( )调用中 INADDR_ANY 0 IP 地址和端口号都由系统内核自动指定 这种方式常用于客户端的 bind( )调用中 指定本地 IP 地址 非 0 IP 地址和端口号都由bind( )函数中的参数指定 这种方式常用于主机有多个 IP 地址的服务器端 bind( )调用中 指定本地 IP 地址 0 端口号由内核自动指定 用于客户端 bind( )调用中 第第6章章 网络程序设计基本知识网络程序设计基本知识 在程序中使用bind()调用的典型方式如下所示:#include SOCKET s;sockaddr_in tcpaddr;int iSockErr;i

50、nt port=5000;/端口号/先创建一个使用IP地址族的流式套接口s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);第第6章章 网络程序设计基本知识网络程序设计基本知识 /以下给结构类型的地址提供数值tcpaddr.sin_family=AF_INET;/htons()函数把一个16位主机字节顺序的端口号转化为网络字节顺序tcpaddr.sin_port=htons(port); /htons()函数把一个32位主机字节顺序的IP地址转化为网络字节顺序tcpaddr.sin_addr.s_addr=htonl(INADDR_ANY);第第6章章 网络程序

51、设计基本知识网络程序设计基本知识 i f ( b i n d ( s , ( L P S O C K A D D R ) & t c p a d d r, sizeof(tcpaddr)= SOCKET_ERROR) /该函数的调用失败,进行错误处理iSockErr=WSAGetLastError();/根据不同的错误类型进行输出提示信息return;/函数调用成功,进行其他处理第第6章章 网络程序设计基本知识网络程序设计基本知识 该程序段是使用bind()调用常用的形式,由内核指定IP地址,应用程序指定端口号。至此,通信过程中一端的协议、地址和所使用的端口号已经确定,一个套接口就可以

52、正常使用了,即可以进行数据的接收或发送操作了。第第6章章 网络程序设计基本知识网络程序设计基本知识 6.4.4 监听连接listen()在一个服务器端用socket()调用成功创建了一个套接口,并用bind()函数和一个指定的地址关联(即绑定)在一起后,要指示该套接口进入监听连接请求的状态以及接收由客户发出的连接请求,就要用到Winsock API函数listen()。 1函数格式 listen()函数格式如下: int listen( SOCKET s, int backlog );第第6章章 网络程序设计基本知识网络程序设计基本知识 2函数参数说明listen()函数中各参数说明如下: s

53、:用于标识一个已绑定了地址,但还未建立连接的套接口描述字。 backlog:该参数指定了正在等待连接的最大队列长度。这个参数非常重要,因为完全可能同时出现几个对服务器的连接请求。例如,假定backlog参数为2时有三个客户机同时发出连接请求,那么前两个会被放在一个“等待处理”队列中,以便应用程序依次为它们提供服务。第第6章章 网络程序设计基本知识网络程序设计基本知识 而第三个连接的请求会造成一个WSAECONNREFUSED错误。一旦服务器接受了一个连接请求,那个连接请求就会从队列中删去,以便可以继续接收其他客户发出的连接请求。要注意的是,backlog参数本身的大小就存在着限制,这个限制是由

54、协议提供者决定的。3函数返回信息如果listen()函数的调用无错误发生,则返回值为0,否则返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应的错误代码。下面是可能获得的错误代码的说明:第第6章章 网络程序设计基本知识网络程序设计基本知识 WSANOTINITIALISED:在使用此API之前应成功调用WSAStartup(); WSAENETDOWN:Windows套接口实现检测到网络子系统失效; WSAEADDRINUSE:试图用listen()去监听一个正在使用中的地址; WSAEINPROGRESS:一个阻塞的Windows套接口调用正在运行中;

55、 WSAEINVAL:该套接口未用bind()进行捆绑,或已被连接;第第6章章 网络程序设计基本知识网络程序设计基本知识 WSAEISCONN:套接口已被连接; WSAEMFILE:无可用文件描述字; WSAENOBUFS:无可用缓冲区空间; WSAENOTSOCK:描述字不是一个套接口WSAEOPNOTSUPP:该套接口不能正常支持对listen()的调用。4函数使用说明l i s t e n ( ) 仅 适 用 于 支 持 连 接 的 套 接 口 , 如SOCK_STREAM类型的套接口。也就是说,在IP地址族中,它只适用于同时有多个连接请求的TCP服务器。如果当一个连接请求到来时队列已满

56、,那么客户将收到一个WSAECONNREFUSED错误。第第6章章 网络程序设计基本知识网络程序设计基本知识 6.4.5 请求连接connect()或WSAConnect()当服务器端建立好套接口并与一个本地地址绑定后,就进入监听状态,等待客户发出连接请求,从而为客户提供服务。在客户端当套接口建立好之后,就要调用connect()函数,提出与一个服务器建立连接的请求,如果服务器接受请求,就可以在服务器的远程套接口与客户端的本地套接口之间建立一条连接。第第6章章 网络程序设计基本知识网络程序设计基本知识 1函数格式在Winsock 1中提供的connect()函数格式是:int connect(

57、SOCKET s,const struct sockaddr FAR* name,int namelen);第第6章章 网络程序设计基本知识网络程序设计基本知识 在Winsock 2中提供的扩展格式是: int WSAConnect(SOCKET s,const struct sockaddr FAR* name,int namelen,LPWSABUF lpCallerData,LPWSABUF lpCalleeData,LPQOS lpSQOS,LPQOS lpGQOS);它是Winsock 2对connect()函数的扩展版本,支持连接数据交换和确定服务质量(QOS)。 第第6章章 网络

58、程序设计基本知识网络程序设计基本知识 2函数参数说明connect()函数中各参数说明如下:s:将要建立连接的套接口描述字。name:是一个指向远端套接口地址结构(sockaddr_in)的指针,表示s套接口欲与其建立一条连接。namelen:name名字的长度。Winsock 1中提供的请求建立连接函数的格式和Winsock 2提供的扩展格式前三个参数是完全一样的。Winsock 2中后四个参数的含义是:lpCallerData:指向用户数据缓冲区的一个指针,该缓冲区中包含有在建立连接时由本机传输到服务器端(远端)的数据。第第6章章 网络程序设计基本知识网络程序设计基本知识 lpCallee

59、Data:指向另一个用户数据缓冲区的指针,该缓冲区中包含在建立连接时从服务器端(远端)传送到本机的数据。以上两个参数都是WSABUF结构型的指针,WSABUF是一种在Winsock 2中很常用的结构,该结构的定义如下:typedef struct _WSABUF intlen;/ the length of the bufferchar FAR *buf;/ the pointer to the bufferWSABUF, FAR* LPWSABUF;第第6章章 网络程序设计基本知识网络程序设计基本知识 根据该结构具体应用的不同,len字段要么指定由buf字段指向的那个缓冲区的长度,要么指定包

60、含在数据缓冲区buf中的数据长度。在该函数中len字段显然表示缓冲区的长度。 lpSQOS:是一个指向服务质量(QOS)结构的指针,它用于指定流式套接口s需要的服务质量,在数据的发送与接收方各有一个;若为空值,则表明没有对该应用指定专用的QOS。 lpGQOS:也是一个指向服务质量(QOS)结构的指针,它指出套接口组所需要的服务质量;目前,尚未提供对套接字组的支持,因此该指针可设置为NULL。第第6章章 网络程序设计基本知识网络程序设计基本知识 这两个参数都是QOS型的指针,QOS结构的定义如下:typedef struct _QualityOfService WSABUFSendingFlowspec;/

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论