网络编程技术西电ppt课件第3章.ppt
《网络编程技术西电ppt课件第3章.ppt》由会员分享,可在线阅读,更多相关《网络编程技术西电ppt课件第3章.ppt(82页珍藏版)》请在三一办公上搜索。
1、思考题:Unix与Windows的区别,界面友好?单线程/多线程?操作习惯?,第3章 Windows环境的网络编程,Windows Sockets 规范Winsock 规范与Berkeley套接字的区别Winsock 1.1 的库函数Winsock 2 介绍Winsock 1.1 的基础编程,3.1 Windows Sockets规范,3.1.1 概述Microsoft公司以Berkeley Sockets规范为范例,定义了Windows Socktes规范,简称Winsock规范。这是Windows操作系统环境下的套接字网络应用程序编程接口(API)。包含:Berkeley Socket 风
2、格的库函数;针对Windows操作系统的扩展库函数。可以充分利用Windows的消息驱动机制编程。Winsock规范定义了应用程序开发者能够使用,并且网络软件供应商能够实现的一套库函数和相关语义,让各个软件供应商共同遵守,做到Winsock兼容。,图3.1 网络应用进程利用Windock进行通信,3.1.2 Windows Sockets规范Windows Sockets 规范是一套开放的、支持多种协议的Windows下的网络编程接口。从1991年到1995年,从1.0版发展到2.0.8版,已成为Windows网络编程的事实上的标准。1Windows Sockets 1.1版本在Winsock
3、.h包含文件中,定义了WinSock 1.1版本库函数的语法、相关的符号常量和数据结构。库函数的实现在Winsock.dll动态链接库文件中。,(1)WinSock 1.1 全面继承了Berkeley Sockets规范。Winsock1.1继承了Berkeley Sockets规范的主要特征,一部分库函数与之在形式上保持一致,包括库函数的名称、参数格式、结构定义。见表 3.1。其中,带*号的表明该例程在某些情况下可能会发生阻塞。,表3.1 WinSock 1.1继承Berkeley Sockets的函数,表3.1 WinSock 1.1继承Berkeley Sockets的函数(cont.)
4、,(2)数据库函数表3.2列出了Winsock规范定义的数据库查询函数。其中6个采用getXbyY()的形式,大多要借助网络上的数据库来获得信息,而不采用本地数据库来实现。,getXbyY()形式的数据库例程都返回一个指针,指向某种类型的结构区域,用来存放函数返回的数据信息。这些结构区域是由winsock实现(即Winsock.dll)分配的,由系统管理,所以指针指向的结构数据是易失的,只在该线程的下一个Winsock API调用前有效。一个线程中只有一个该结构的副本,因此应用程序在发出下一个Winsock API调用前,应把所需的信息复制下来。应用程序不应试图修改或释放这个结构。,(3)Wi
5、nSock 1.1 扩充了Berkeley Sockets规范针对微软 Windows的特点,WinSock 1.1定义了一批新的库函数,提供了对消息驱动机制的支持,有效地利用Windows多任务多线程的机制。扩充主要是提供了一些异步函数,增加了符合Windows消息驱动特性的网络事件异步选择机制,有利于开发符合Windows编程模式的软件,使得开发高性能网络通信程序成为可能。这些扩充函数的名字都以WSA开头,后面跟async表示是专为实现异步机制而设置的。编程时必须使用WSAStartup()和WSACleanup(),其它函数随意使用。,12,表3.3 Winsock 1.1的常用扩展函数
6、,13,表3.3 Winsock 1.1的常用扩展函数(续),(4)WinSock 1.1只支持TCP/IP协议栈 Winsock 1.1的实现,即Winsock.dll和底层协议栈的接口是唯一的,且是独占的,只能访问TCP/IP协议栈。因此,Winsock 1.1套接字仅支持单一的通信域,即Internet域。,2WinSock 2.0规范WinSock 2.0在源码和二进制代码方面与WinSock 1.1兼容,此外还增强了许多功能。(1)支持多种协议(2)引入了重叠I/O的概念(3)使用事件对象异步通知(4)服务的质量(QOS)(5)套接字组(6)扩展的字节顺序转换例程(7)分散/聚集方式
7、I/O(8)新增了许多函数。,3.WinSock 1.1中的阻塞问题阻塞是在把应用程序从Berkeley套接字环境中移植到Windows环境中的一个主要焦点,虽然Windows Sockets支持关于套接字的阻塞操作,但是这种应用是被强烈反对的。阻塞,是指唤起一个函数,该函数直到相关操作完成时才返回。在Berkeley套接字模型中,一个套接字的操作的缺省行为是阻塞方式的,除非程序员显式地请求该操作为非阻塞方式。在Windows环境下,强烈推荐程序员尽可能使用非阻塞方式(异步方式)的操作,因为非阻塞方式的操作能够更好地在非占先的Windows环境下工作。,有些Sockets操作在阻塞和非阻塞方式
8、下没什么区别;而有些Sockets操作取决于传输情况,会立即完成或阻塞一段时间。当操作用于阻塞套接字(打*号标记的)时,这些操作被认为是工作于阻塞方式的。在Windows Sockets实现中,一个无法立刻完成的阻塞操作是按如下方式处理的:DLL先初始化操作,然后进入一个循环,在循环中发送收到的任何信息,以便必要时将处理器交给其它线程;然后检查Windows Sockets功能是否完成,如果完成了,WSACancleBlockingCall()被唤起,阻塞操作以一个适当的返回值结束。,如果一个正在运行某一阻塞操作的进程收到了一个Windows消息,那么应用程序有可能试图发出另一个Windows
9、 Sockets调用。由于难以安全的处理这种情况,Windows Sockets规范不支持这种应用程序的工作方式,此时可以借助两个函数来解决:WSAIsBlocking()可以用来确定在该进程上是否有阻塞的Windows Sockets调用;WSACancleBlockingCall()可以用来取消在线的阻塞调用,如果有的话。其它任何Windows Sockets函数此时被调用,都会失败并返回错误代码WSAEINPROGRESS。这一限制适用于所有阻塞和非阻塞操作。,3.1.3 WinSock规范与Berkeley套接字的区别,1套接字数据类型和该类型的错误返回值在UNIX中,包括套接字句柄在
10、内的所有句柄,都是非负的短整数;在WinSock规范中定义了一个新的数据类型,称作SOCKET,用来代表套接字描述符。typedef u_int SOCKET;socket()和accept()函数返回时,返回的就是SOCKET类型。SOCKET可以取从0到INVALID_SOCKET-1之间的任意值。,要判断socket()和accept()是否正确执行,可以将返回值和INVALID_SOCKET来比较,该常量已在Winsock.h中定义。例如:在UNIX套接字规范中s=socket();if(s=-1)执行错误处理代码 在Winsock套接字规范中:s=socket();if(s=INVA
11、LID_SOCKET)执行错误处理代码,2select()函数和FD_*宏在Winsock中,可以使用select()函数来选择对某些事件的处理,比如连接请求到来、有数据待接收等等。应用程序采用FD_XXX宏来设置、初始化、清除和检查fd_set结构(用来代表一组套接字)。3错误代码的获得UNIX套接字规范中,如果函数执行时发生了错误,会把错误代码放到errno或h_errno变量中。在Winsock中错误代码可以使用WSAGetLastError()调用得到。4指针所有应用程序与Windows Sockets使用的指针都必须是FAR指针,访问距离超过了64K,适用于大程序。,5.重命名的函数
12、有两个伯克利套接字函数改了名字,避免与其它API冲突。close()改变为closesocket()ioctl()改变为ioctlsocket()6.Winsock支持的最大套接字数目一个特定的Windows Sockets提供者所支持的套接字的最大数目是由实现确定的;任何一个应用程序都不应假设某个待定数目的套接字可用。一个Windows Sockets应用程序可以使用的套接字的最大数目在Winsock.h中缺省值是64,在编译时由常量FD_SETSIZE决定。,7.头文件Berkeley头文件被包含在Winsock.h中。一个Windows Sockets应用程序只需简单地包含Winsock
13、.h就足够了。8原始套接字Windows Sockets规范并没有规定Windows Sockets DLL必须支持原始套接字(用SOCK_RAW打开的套接字),但是鼓励提供原始套接字支持。9、Winsock规范对于消息驱动机制的支持体现在异步选择机制、异步请求函数、阻塞处理方法、错误处理、启动和终止等方面。,3.2 Winsock 1.1的库函数,3.2.1 Winsock的注册与注销 1初始化函数WSAStartup()Winsock应用程序要做的第一件事,就是必须首先调用WSAStartup()函数对Winsock进行初始化。初始化也称为注册,注册成功后,才能调用其他的Winsock A
14、PI函数。(1)WSAStartup()函数的调用格式int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);wVersionRequested:应用程序要使用的winsock最高版本号;lpWSAData:指向WSADATA结构,返回Winsock API实现细节。,图3.2 在一台计算机中,使用同一Winsock实现的多个网络应用程序,(2)WSAStartup()函数的初始化过程,26,(3)WSADATA结构的定义#define WSADESCRIPTION_LEN 256#define WSASYS_STATUS_LEN
15、128typedef struct WSAData WORD wVersion;WORD wHighVersion;char szDescriptionWSADESCRIPTION_LEN+1;char szSystemStatusWSASYS_STATUS_LEN+1;unsigned short iMaxSockets;unsigned short iMaxUdpDg;char*lpVendorInfo;WSADATA;,27,(4)初始化函数可能返回的错误代码WSASYSNOTREADY:网络通信依赖的网络子系统没有准备好。WSAVERNOTSUPPORTED:找不到所需的Winsock
16、 API相应的动态连接库。WSAEINVAL:DLL不支持应用程序所需的Winsock版本。WSAEINPROGRESS:正在执行一个阻塞的Winsock 1.1操作。WSAEPROCLIM:已经达到Winsock支持的任务数上限。WSAEFAULT:参数lpWSAData不是合法指针。,28,(5)初始化Winsock的示例#include/对于Winsock 2.2,应包括 Winsock2.h文件main()WORD wVersionRequested;/应用程序所需的Winsock版本号WSADATA wsaData;/用来返回Winsock 实现的细节信息int err;/出错代码。
17、wVersionRequested=MAKEWORD(1,1);/生成版本号1.1err=WSAStartup(wVersionRequested,/*至此,可以确认初始化成功,Winsock.DLL可用。,2注销函数WSACleanup()程序使用完Winsock.DLL提供的服务后,应用程序必须调用WSACleanup()函数,来解除与Winsock.DLL库的绑定,释放Winsock实现分配给应用程序的系统资源,中止对Windows Sockets DLL的使用。(1)WSACleanup()函数的调用格式int WSACleanup(void);返回值:如果操作成功返回0,否则返回SO
18、CKET_ERROR.,29,(2)WSACleanup()函数的功能对应于一个任务进行的每一次WSAStartup()调用,必须有一个WSACleanup()调用。只有最后的WSACleanup()做实际的清除工作;前面的调用仅仅将Windows Sockets DLL中的内置引用计数递减。一个简单的应用程序为确保WSACleanup()调用了足够的次数,可以在一个循环中不断调用WSACleanup()直至返WSANOTINITIALISED。(3)WSACleanup()函数可能返回的错误代码WSANOTINITIALISED:在调用本API之前应成功调用WSAStartup()。WSAE
19、NETDOWN:检测到网络子系统失效。WSAEINPROGRESS:一个阻塞的WinSock调用正在进行中,或者服务提供者仍在处理一个回调函数。,30,3.2.2 Winsock的错误处理函数Winsock函数执行时都有一个返回值,只能说明函数的执行成功与否,不能从返回值了解出错原因。1WSAGetLastError()函数int WSAGetLastError(void);返回本线程进行的上一次Winsock函数调用时,产生的错误代码。在Winsock.h中定义了所有的错误代码,基数是100002WSASetLastError()函数void WSASetLastError(int iErr
20、or);本函数允许应用程序为当前线程设置错误代码,并可由后来的WSAGetLastError()调用返回。,3.2.3 主要的Winsock函数1创建套接字socket()SOCKET socket(int af,int type,int protocol);返回值:创建成功,返回套接字描述符,否则返回SOCK_ERROR。举例:SOCKET sockfd=socket(AF_INET,SOCK_STREAM,0);/*创建一个流式套接字。SOCKET sockfd=socket(AF_INET,SOCK_DGRAM,0);/*创建一个数据报套接字。,2将套接字绑定到指定的网络地址BIND()
21、int bind(SOCKET s,const struct sockaddr*name,int namelen);有许多函数都需要套接字的地址信息,像UNIX 套接字一样,Winsock也定义了三种关于地址的结构,经常使用。通用的Winsock地址结构,针对各种通信域的套接字,存储它们的地址信息。struct sockaddr u_short sa_family;/*地址家族 char sa_data14;/*协议地址,33,专门针对Internet 通信域的Winsock地址结构struct sockaddr_in short sin_family;/*指定地址家族,一定是AF_INET.
22、u_short sin_port;/*指定将要分配给套接字的传输层端口号,struct in_addr sin_addr;/*指定套接字的主机的IP 地址 char sin_zero8;/*全置为0,是一个填充数。专用于存储IP地址的结构struct in_addr union struct u_char s_b1,s_b2,s_b3,s_b4;s_un_b;struct u_short s_w1,s_w2;s_un_w;u_long s_addr;,34,在使用Internet域的套接字时,这三个数据结构的一般用法是:首先,定义一个sockaddr_in的结构实例变量,并将它清零;然后,为这
23、个结构的各成员变量赋值;第三步,在调用bind()绑定函数时,将指向这个结构的指针强制转换为 sockaddr*类型。,35,举例:SOCKET serSock;/定义了一个SOCKET 类型的变量。sockaddr_in my_addr;/定义一个Sockaddr_in型的结构实例变量。int err;/出错码。int slen=sizeof(sockaddr);/sockaddr 结构的长度。serSock=socket(AF_INET,SOCK_DGRAM,0);/创建数据报套接字。memset(my_addr,0,slen);/将sockaddr_in的结构实例变量清零。my_addr
24、.sin_family=AF_INET;/指定通信域是Internet。my_addr.sin_port=htons(21);/指定端口,将端口号转换为网络字节顺序。,36,/*指定IP地址,将IP地址转换为网络字节顺序。my_addr.sin_addr.s_addr=htonl(INADDR-ANY);/*将套接字绑定到指定的网络地址,对/*以下可以报错,进行错误处理。,37,3启动服务器监听客户端的连接请求listen()int listen(SOCKET s,int backlog);仅适用于支持连接的SOCK_STREAM类型的套接字。套接字s处于一种“变动”模式,申请进入的连接请求被
25、确认,并排队等待被接受。这个函数特别适用于同时有多个连接请求的服务器;如果当一个连接请求到来时,队列已满,那么客户将收到一个WSAECONNREFUSED错误。,38,4接收连接请求accept()SOCKET accept(SOCKET s,struct sockaddr*client_addr,int*addrlen);s 是服务器正在侦听的套接字,accept()之后变回侦听状态。如果返回值是INVALID_SOCKET表示失败,否则就是返回成功建立的新套接字,用来与这个客户通信成功时client_addr 中包含客户IP和端口,39,5请求连接connect()int connect(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网络 编程 技术 ppt 课件
链接地址:https://www.31ppt.com/p-4081705.html