1 / 77

网络编程技术

网络编程技术. 授课教师 : 谭献海 Email : xhtan@swjtu.edu.cn. 网络编程技术 直接网卡编程(可编程芯片) 基于 packet driver 的编程技术 基于 NDIS 的网络编程 VPACKET , PACKET32 Berkeley Sockets 编程技术 Winsock JAVA 网络编程. 网络编程技术概述. 一、 Winsock 概述 Windows 网络编程规范- Windows Sockets 是 Windows 下得到广泛应用的、开放的、支持多种协议的 socket 网络编程接口。

reeves
Download Presentation

网络编程技术

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 网络编程技术 授课教师:谭献海 Email:xhtan@swjtu.edu.cn

  2. 网络编程技术 直接网卡编程(可编程芯片) 基于packet driver的编程技术 基于NDIS的网络编程 VPACKET,PACKET32 Berkeley Sockets编程技术 Winsock JAVA网络编程 网络编程技术概述

  3. 一、Winsock概述 Windows网络编程规范-Windows Sockets是Windows下得到广泛应用的、开放的、支持多种协议的socket网络编程接口。 Windows Sockets规范以U.C. Berkeley大学BSD UNIX中流行的Socket接口为范例,定义了一套Windows下的网络编程接口。它不仅包含了人们所熟悉的Berkeley Socket风格的库函数;也包含了一组针对Windows的扩展库函数,以便充分地利用Windows消息驱动机制和异步I/O选择进行编程。 Winsock

  4. winsock有开发组件和运行组件二大部分 开发组件供开发应用程序使用,包括定义的宏常量、数据结构和函数调用接口原型。 运行组件是winsock应用程序接口的动态链接库—winsock.DLL,应用程序在执行时通过装入DLL实现网络通信功能。 Winsock

  5. 应用程序调用Windows Sockets的API实现相互之间的通信,Windows Sockets又利用下层的网络通信协议和操作系统调用实现实际的通信工作。 应用程序2 应用程序1 网络编程接口winsock 网络通信协议服务接口TCP/IP 操作系统 windows 物理通信介质 图1 winsock所处的位置 Winsock所处的位置

  6. Windows 平台支持的Winsock 版本 • 采用Winsock 1的应用必须有Winsock.h头文件 • 使用Winsock 2的应用需要Winsock2.h头文件。

  7. Winsock有两个主要的版本,即Winsock1和Winsock2 头文件:编写与Winsock1兼容的程序需要引用头文件WINSOCK.H,如果编写使用Winsock2的程序,需要引用WINSOCK2.H;此外还有一个MSWSOCK.H头文件,它是专门用来支持在Windows平台上高性能网络程序扩展功能的 库文件:使用WINSOCK.H头文件时,同时需要库文件WSOCK32.LIB;使用WINSOCK2.H时,则需要WS2_32.LIB;如果使用MSWSOCK.H中的扩展API,则需要MSWSOCK.LIB 构建编程环境

  8. 每个Winsock 应用都必须加载Winsock DLL的相应版本。 加载Winsock 库是通过调用WSAStartup函数实现的。 如果调用Winsock函数之前,没有加载Winsock 库,就会返回一个SOCKET_ERROR,对应的错误信息是WSANOTINITIALISED。 在通信应用程序的最后调用WSACleanup来释放所使用的Windows Sockets DLL Winsock的初始化与卸载

  9. WInsock2 程序的大致框架 WSAStartup(初始化Windows Sockets API) 应用程序 WSACleanup(释放所使用的Windows Sockets DLL)

  10. 二、Winsock提供的函数调用 WinSock包括三类函数: Berkeley socket函数 检索有关域名、通信服务和协议等Internet信息的数据库函数 Berkekley socket例程的Windows专用的扩展函数 Winsock函数

  11. WinSock函数分为阻塞和非阻塞函数。创建一个socket时,可以指定它是否为阻塞。WinSock函数分为阻塞和非阻塞函数。创建一个socket时,可以指定它是否为阻塞。 在缺省情况下,Berkeley的Socket函数和WinSock都创建“阻塞”的socket。 阻塞socket可以通过使用select函数或者WSAAsynSelect函数将指定操作(如接收、发送、异常等)变成非阻塞操作。 Winsock

  12. 2.1 基本套接口函数Windows Sockets规范包含了以下30个Berkeley风格的套接口例程(与Berkeley socket兼容): * 表示该函数为阻塞方式。 Winsock

  13. 基本套接口函数 • socket() 创建一个socket并返回一个套接口句柄 • bind() 把一个本地名字和一个无名的套接口捆绑起来 • Listen() 服务器监听 • accept()* 响应连接请求,并且新建一个套接口。原来 的套接口则返回监听状态。 • connect()* 初始化到一个指定套接口上的连接 • getpeername() 得到连接在指定套接口上的对等通信方 的名字。 • getsockname() 得到指定套接口的名字。 • getsockopt() 得到与指定套接口相关的属性选项。

  14. recv()* 从一个已连接的套接口接收数据(面向连接) recvfrom()* 从一个的套接口接收数据(无连接) send()* 向一已连接的套接口发送数据(面向连接) sendto()* 向套接口发送数据(无连接) select()* 执行同步I/O多路复用。 setsockopt() 设置与指定套接口相关的属性选项。 Close() 关闭套接口 shutdown() 关闭一部分全双工的连接。 *表示例程在应用于阻塞套接口时会阻塞。 基本套接口函数

  15. htonl() 把32位的数字从主机字节顺序转换到网络字节顺序 htons() 把16位的数字从主机字节顺序转换到网络字节顺序 ntohl() 把32位数字从网络字节顺序转换为主机字节顺序 ntons() 把16位数字从网络字节顺序转换为主机字节顺序 inet_addr() 把一个十进制“.”分IP地址转换成二进制IP地址 inet_ntoa()把一个二进制IP地址转换成十进制“.”分IP地址 ioctlsocket() 套接口I/O控制,用于设置套接口的I/O模式 基本套接口函数

  16. 2.2 数据库函数Windows Sockets规范定义了如下数据库函数: gethostbyaddr()*根据网络地址得到对应的主机信息 gethostbyname() *根据主机名得到对应的主机信息(IP地址,可能多个) gethostname()得到本地主机名 getprotobyname()*根据协议名得到对应的协议信息 getprotobynumber()*根据协议号得到对应的协议名 getservbyname()*根据一个服务的名字得到对应的服务信息 getservbyport()*从根据一个端口号得到对应的服务信息 *表示该函数在某些情况下可能会阻塞 数据库函数

  17. Winsock扩展的函数 主要针对windows的消息机制和异步IO选择来扩展

  18. Windows是一个“基于事件和消息驱动的”操作系统。Windows是一个“基于事件和消息驱动的”操作系统。 Windows内部机制 系统检测到后 发给应用程序 用户进行了影响窗口的动作 “事件” “消息” 触发 处理消息

  19. 2.3 针对Microsoft Windows的扩展函数 为了适应Windows下的消息机制和异步I/O选择操作,Windows Sockets API在功能上扩充了将近20个函数,所有扩充的函数均冠以前缀WSA(Windows Sockets Asynchronous)。这些扩展的API是为了应用程序能更好地处理基于消息的异步网络事件。 虽然基于Windows Sockets的编程并不强制使用这个扩展的API集(WSAStartup()和WSACleanup()除外)但推荐应用程序开发者遵循Microsoft Windows的编程范例。 Winsock扩充的函数

  20. WSAAsyncGetHostByAddr()获取对应于一个地址的主机信息(一个标准的Berkeley的getXbyY()函数集合的异步版本 ) WSAAsyncGetHostByName() 获取对应于一个主机名的主机信息(异步版本) WSAAsyncGetProtoByName() 获取对应于一个协议名的协议信息(异步版本) WSAAsyncGetProtoByNumber()获取对应于一个协议号的协议信息(异步) WSAAsyncGetServByName() 获取对应于一个服务名的服务信息(异步) WSAAsyncGetServByPort() 获取对应于一个端口号的服务信息(异步版本) WSAAsyncSelect()select()函数的异步版本。 Winsock扩充的函数

  21. WSACancelAsyncRequest()取消一个未完成的WSAAsyncGetXByY()函WSACancelAsyncRequest()取消一个未完成的WSAAsyncGetXByY()函 数的实例。 WSACancelBlockingCall()取消未完成的阻塞API调用。 WSAStartup()初始化底层的Windows Sockets DLL WSACleanup()撤销底层的Windows Sockets DLL注册。 WSAGetLastError()得到最近的一个Windows Sockets API调用错误信息 WSASetLastError()设置最近一次错误信息 WSAIsBlocking()该线程是否已经被一个调用阻塞 WSASetBlockingHook()为底层的Windows Sockets实现设置阻塞嵌 入(hook)程序入口 WSAUnhookBlockingHook()恢复缺省的阻塞嵌入(hook)处理程序 Winsock扩充的函数

  22. winsock的启动与关闭 网络通信必须通过启动函数WSAStartup()启动winsock,装载动态链接库; 对于每一个WSAStartup的调用必须对应一个WSACleanup的调用,这个函数的作用是释放相应的WinSock库,函数原型为: Int WSACleanup(void); Winsock对Berkeley socket的扩充

  23. int WSAStartup( WORD wVersionRequested, LPWSDATA lpWSAData ) wVersionRequested:指定要加载的winsock库的版本,高字节为次版本号,低字节为主版本号。它的值可使用宏MAKEWORD(x,y)来建立,x为次版本号,y为主版本号 lpWSAData:一个指向WSADATA结构的指针,用来返回DLL库的详细信息 WSAStartup()函数

  24. typedef struct WSAData{ WORD wVersion; //库文件建议应用程序使用的版本 WORD wHighVersion; //库文件支持的最高版本 char szDescription[WSADESCRIPTION_LEN+1]; //库描述字符串 char szSystemStatus[WSASYS_STATUS_LEN+1]; //系统状态字符串 unsigned short iMaxSockets; //同时支持的最大套接字数量 //以下两个参数在2.0版中已废弃 unsigned short iMaxUdpDg; char FAR* lpVendorInfo; } WSDATA,FAR * LPWSADATA; 结构体WSADATA

  25. #include <stdio.h> //引入winsock库 #include <winsock2.h> #pragma comment(lib,"WS2_32") #pragma是标准C/C++的内容,用于向编译器传递特定参数。具体参数则与编译器有关 其中comment(lib,“WS2_32”)特定于VC的参数,并不通用 //加载winsock库 void initSocket(BYTE,BYTE); //释放winsock库 void cleanSocket(); winsock的启动与关闭程序实例

  26. void initSocket(BYTE minorVer,BYTE majorVer) { WSADATA wsaData; WORD sockVersion = MAKEWORD(minorVer,majorVer); if (WSAStartup(sockVersion,&wsaData)!=0) { exit(0); } } void cleanSocket() { WSACleanup(); } 加载、释放winsock库(WS2_32.DLL)

  27. 异步选择机制 在windows sockets中提供了一组异步扩展函数,实现基于消息机制的网络通信编程,其中关键是提供了对网络事件基于消息的异步存取,其核心是异步选择函数WSAAsyncSelect()。 WSAAsyncSelect()函数用来注册应用程序感兴趣的网络事件,当这些网络事件发生时,应用程序相应的窗口函数将得到一个消息,应用程序根据该消息进行判断,完成相应的操作。 Winsock对Berkeley socket的扩充

  28. WSAAsyncSelecet ()函数的原型为: int PASCAL FOR WSAAsyncSelect(SOCKET s,HWND hWnd,unsigned int wMsg,long lEvent); 参数含义: SOCKET s--应用程序申请到的套接字句柄 hWnd--接收winsock消息的窗口句柄 wMsg--向窗口hWnd发出的消息的名称 lEvent--被注册的网络事件 功能描述: 请求winsock.DLL在检测到套接字s上发生的某个网络事件IEvent时,向窗口hWnd发送一个消息wMSG,并自动地设置套接字处于非阻塞工作方式。其中的事件可以是一个或多个的组合,事件之间用“|”分隔。 通常事件包括允许读数据,写数据、连接、接纳、关闭、带外数据等六种。 利用重载以下成员函数来处理各种网络事件。 Winsock对Berkeley socket的扩充

  29. 标记 事件 需要重载的函数 FD_READ 有数据到达时发生 void OnReceive( int nErrorCode ); FD_WRITE 允许数据发送时产生 void OnSend( int nErrorCode ); FD_OOB 收到外带数据时发生 void OnOutOfBandData( int nErrorCode ); FD_ACCEPT 有连接请求到达时发生 void OnAccept( int nErrorCode ); FD_CONNECT 作为客户端连接成功时发生 void OnConnect( int nErrorCode ); FD_CLOSE 套接口关闭时发生 void OnClose( int nErrorCode ); Winsock对Berkeley socket的扩充

  30. lEvent可以是一种或多种网络事件的组合(需要多个网络事件的组合时通过OR操作符(|)来表示),例如,如果我们希望在套接字S上收到数据或允许发送数据时收到消息,这时函数的调用格式为:lEvent可以是一种或多种网络事件的组合(需要多个网络事件的组合时通过OR操作符(|)来表示),例如,如果我们希望在套接字S上收到数据或允许发送数据时收到消息,这时函数的调用格式为: WSAAsyncSelect(s,hWnd,wMsg, FD_READ|FD_WRITE); Winsock对Berkeley socket的扩充

  31. 异步请求服务 异步数据库函数允许应用程序以异步方式请求信息。 WSAAsyncGetXByY()函数允许应用程序开发者不必象在使用Berkeley标准函数时阻塞整个Windows环境 WSACancelAsyncRequest()函数允许一个应用程序取消未完成的异步WSAAsyncGetXByY()请求 Winsock对Berkeley socket的扩充

  32. 利用阻塞HOOK进行阻塞处理 windows是一个异步操作系统,在windows内任何事件都是异步发生的。事件发生后,windows向程序启动此操作时指定的窗口发送一个消息 windows中对消息的处理由类似于下面的循环语句完成 MSG msg; /* 定义消息类型*/ While(GetMessage(&msg,NULL,0,0 ) ) { TranslateMessage (&msg) ; /*对该消息进行翻译 */ DispatchMessage (&msg) ; /* 分发消息*/ } 函数GetMessage从消息队列中检索出一条消息,并将它存于具有MSG类型的一个变量中,然后交由函数TranslateMessage对该消息进行翻译,并通过函数DispatchMessage将消息发送到适当的对象上。 在循环语句后通常编写一个消息处理过程(hook)例程来处理该消息。 Winsock对Berkeley socket的扩充

  33. 在winsock中有一个默认的阻塞处理例程BlockingHook(…),这个处理例程是简单地获取并发送winsock消息。在winsock中有一个默认的阻塞处理例程BlockingHook(…),这个处理例程是简单地获取并发送winsock消息。 对于要求更复杂的消息处理的应用程序,应建立自已的处理过程用的Hook程序。为此在winsock的API中提供了WSASetBlockingHook(…)和WSAUnHookBlockingHook(…)两个函数,前者用于定义使用自已的阻塞Hook例程 ,后者用于恢复缺省Hook例程。 winsock提供了两个检测和取消阻塞操作的函数:WSAIsBlocking(viod)和WSACancelBlockingCall(void) 前者检查确定当前是否有阻塞操作,并返回布尔值;若有阻塞操作,应用程序可以进入阻塞操作处理;若有必要调用后者取消当前的阻塞操作 Winsock对Berkeley socket的扩充

  34. 错误处理 如果调用一个Winsock 函数时发生了错误,就可用WSAGetLastError函数来获得最近一个错误代码,这个错误代码明确地表明发生的错误情况。 WSAGetLastError 函数返回的错误都有预定义常量值,根据Winsock 版本的不同,这些值在Winsock .h或Winsock2.h中声明。 Winsock对Berkeley socket的扩充

  35. 常量值说明==============================================sckOutOfMemory 7内存不足 sckInvalidPropertyValue 380属性值不效 sckGetNotSupported394属性不可读 sckGetNotSupported383属性是只读的 sckBadState 40006所请求的事务或请求本身的错误协议或者错 误连接状态 sckInvalidArg 40014传递给函数的参数格式不确定,或者不在指 定范围内 sckSuccess40017成功 sckUnsupported40018不支持的变量类型 sckInvalidOp40020在当前状态下的无效操作 sckOutOfRange 40021参数越界 sckWrongProtocol40026所请求的事务或请求本身的错误协议 sckOpCanceled10004取消操作 sckInvalidArgument10014所请求的地址是广播地址,但未设置标记 Winsock错误代码一览表

  36. sckWouldBlock 10035套接字不成块,而指定操作将使之成块 sckInProgress 10036制造块的Winsock操作在进行之中 sckAlreadyComplete10037完成操作。未进行制作块的操作 sckNotSocket10038描述符不是套接字 sckMsgTooBig10040数据太大,不适于缓冲区的要求,因 而被截断 sckPortNotSupported10043不支持指定的端口 sckAddressInUse 10048地址在使用中 sckAddressNotAvailable10049来自本地机器的不可用地址 sckNetworkSubsystemFailed 10050网络子系统失败 sckNetworkUnreachable 10051当前不能从主机到达网络 sckNetReset 10052在设置SO_KEEPALIVE时连接超时 sckConnectAborted 10053由于超时或者其它失败而中止接连 sckConnectionReset10054通过远端重新设置连接 Winsock错误代码一览表

  37. sckNoBufferSpace10055没有可用的缓存空间 sckAlreadyConnected 10056已连接的套接字 sckNotConnected 10057未接连套接字 sckSockedShutdown10058已关闭套接字 sckTimedout 10060套接字超时 sckConnectionRefused10061强行拒绝连接 sckNotInitialized 10093套接字没有初始化 sckHostNotFound 11001授权应答:未找到主机 sckHostNotFoundTryAgain 11002非授权应答:未找 到主机,重试 sckNonRecoverableError 11003不可恢复的错误 sckNoData 11004无效名,对所请求的类型 无数据记录 Winsock错误代码一览表

  38. 从Windows Sockets 1.1到Windows Socket 2的主要变动有: 1 同时使用多个传输协议为了用户能够同时使用多个传输协议,在Windows Socket 2中,结构有所改变。在Windows Sockets 1.1中,软件开发商所提供的DLL实现了Windows Sockets的API和TCP/IP协议栈。Windows Sockets DLL和底层协议栈的接口是唯一而且独占的。Windows Socket 2改变了这种模型:它定义了一个Windows Sockets DLL和底层协议栈间的标准服务提供接口(SPI),这使得一个Windows Sockets DLL能够同时访问不同软件开发商的多个底层协议栈。 WINSOCK 2.0 的扩充功能

  39. 同时使用多个传输协议

  40. 2 与Windows Socket 1.1应用程序的向后兼容性:源码和二进制代码。 WINSOCK 2.0 的扩充功能

  41. 3 在Windows Sockets中注册传输协议要使Windows Sockets能够利用一个传输协议,该传输协议必须在系统上安装并且在Windows Sockets中注册。 Windows Sockets 2的DLL包含了一组API来完成这个注册过程。这个注册过程包括建立一个新的注册和取消一个已有的注册。 WINSOCK 2.0 的扩充功能

  42. 使用多个协议一个应用程序可以通过WSAEnumProtocols()功能调用来得到目前有多少个传输协议可以使用,并且得到与每个传输协议相关的信息,这些信息包含在PROTOCOL_INFO结构中。 在Windows Sockets 1中仅有一个地址族(AF_INET),它包含了数量不多的一些众所周知的套接口类型和协议标识符。这在Windows Sockets 2中已经有所改变。除了现有的地址族、套接口类型和协议标识符为了兼容性原因被保留以外,Windows Sockets 2加入了许多唯一的但是可能并不为大家所知的地址族、套接口类型和协议标识符。 WINSOCK 2.0 的扩充功能

  43. 4 协议无关的名字解析Windows Sockets 2包含了应用程序可以使用的多种标准化的网络名字服务。Windows Sockets 2应用程序并不需要理解与名字服务相关的许多迥异的接口(例如DNS,NIS,X.5000,SAP等等)。 5 重叠I/O和事件对象Windows Sockets 2引入了重叠I/O的概念并且要求所有的传输协议提供者都支持这一功能。重叠I/O仅能在由WSASocket()函数打开的套接口上使用(使用WSA_FLAG_OVERLAPPED标记)。 WSAIoctl()函数(iocltosocket()函数的增强版本),还可以使用重叠I/O操作的延迟完成特性。 WINSOCK 2.0 的扩充功能

  44. 5.1 事件对象 重叠I/O概念的引入需要建立一个机制使得应用程序能够正确地把发送和接收事件与今后它们完成时的指示相连接。在Windows Sockets 2中,这一点是通过事件对象实现的,与事件对象相关的函数,包括 WSACreateEvent() WSACloseEvent() WSASetEvent() WSAResetEvent() WSAWaitForMultipleEvent() WSAGetOverlappedResult() 5.2 接收操作完成指示 提供给应用程序适当的灵活性,Windows Sockets 2为接收操作完成指示提供了多个选项。它们包括:等待(阻塞)事件对象,检查事件对象和套接口I/O完成例程。 WINSOCK 2.0 的扩充功能

  45. 6.使用事件对象异步通知为了适应一些应用程序(例如精灵程序(守护进程))或者某些没有用户界面的服务程序(它们不使用窗口句柄),Windows Socket 2提供了WSAEventSelect()函数和WSAEnumNetworkEvents()函数。WSAEventSelect()函数和WSAAyncSelect()函数很类似,区别仅在于当一个FD_XXX网络事件发生时,WSAEventSelect()函数将导致一个应用程序指定的事件对象被设置,而WSAAyncSelect()将导致一条Windows消息被发送(例如FD_READ,FD_WRITE等等)。 WINSOCK 2.0 的扩充功能

  46. 7. 服务的质量(QoS)Windows Sockets 2推荐的流规格把QoS特性划分为:1. 源通信描述:应用程序的通讯事件以什么方式被送 入网络。2. 延时性:最大延时和可接受的延时变化(抖动)。3. 需要保证的服务级别:应用程序是否要求对服务质 量的绝对保证。4. 费用:这一项是为将来可以决定有意义的费用时保 留的。5. 服务提供者特定的参数:流规格可以根据具体的提 供者扩展。 WINSOCK 2.0 的扩充功能

  47. 8. 套接口组Windows Sockets 2引入了一个所谓套接口组的概念。它允许应用程序(或者一组共同工作的应用程序)通知底层的服务提供者一组特定的套接口是相关的,它们享有一些特定的性质。组的特性包括了组内单个套接口之间的相关特性和整个组的服务规范的特性。 WINSOCK 2.0 的扩充功能

  48. 9. 共享套接口为了在进程间共享套接口,Windows Sockets 2引入了WSADuplicateSocket()函数。共享套接口是通过对底层的套接口创建附加的套接口描述字实现的。 10.连接建立和拆除的高级函数 WSAAccept()函数 WSAConnect()函数 WSASendDisconnect()函数接收断连 WSARecvDisconnect()函数接收断连。 WINSOCK 2.0 的扩充功能

  49. 11.扩展的字节顺序转换例程Windows Sockets 2提供了一套把16位或者32位数字转换到网络字节顺序或者从网络字节顺序转换的例程。 12. 分散/聚集方式I/OWSASend(),WSASendTo(),WSARecv()和WSARecvFrom()函数都以应用程序缓冲区数组作为输入参数,因此它们可以进行分散/聚集方式(向量方式)的I/O操作。 WINSOCK 2.0 的扩充功能

  50. 13.协议无关的多点通讯Windows Sockets 2支持基本的数据传输以一般的方式使用不同的传输协议。Windows Sockets 2也支持应用程序以一般的方式使用传输协议的多点通讯能力。 WINSOCK 2.0 的扩充功能

More Related