Winsock编程接口.ppt
《Winsock编程接口.ppt》由会员分享,可在线阅读,更多相关《Winsock编程接口.ppt(94页珍藏版)》请在三一办公上搜索。
1、,第二章 Winsock编程接口,Windows套接字简介字节顺序和Winsock的寻址方式 Winsock API 基本函数 数据报套接字编程流式套接字编程,1.Windows 套接字简介,Winsock来源,Sockets本来是Unix操作系统上流行的一种网络编程接口(API)。API:Application Programming Interface发展过程:1983年在Berkeley大学4.2BSD UNIX中首先使用,因此被称为Berkeley Socket API(只支持TCP/IP协议)。后来在4.3BSD UNIX中增加了对OSI网络协议的支持。应用平台:UNIX、LINUX
2、产生Winsock:Winsock API在1991年根据4.3BSD UNIX的Berkeley Socket制定的。,Winsock规范,Winsock 规范:一套开放的、支持多种协议的Windows下的网络编程接口。主要支持TCP/IP协议。Winsock 规范主要包括Windows提供的API函数:符合Berkeley Socket风格的库函数;针对Windows的一组扩展库函数。发展过程:1991年的1.0版到1997年的2.2版(主要扩充了对其它协议的支持)。应用平台:Windows系列,Winsock实现库两个版本:Winsock1和Winsock2。现在大都使用Winsock2
3、,Winsock2库的最新版本是2.2。,Winsock实现库,采用Winsock 1的应用必须包含winsock.h 头文件。使用Winsock 2的应用必须包含winsock2.h 头文件。,不同平台对应不同的库版本。,套接字基本概念,套接字可以看成是两个网络应用程序进行通信时,各自通信连接中的一个端点。,在编写网络应用程序时,应先申请套接字,以后两台机器上的程序通过该套接字进行通信。,在网络程序编程中,通过将IP、端口与一个套接字绑定,并指明通信协议,从而来实现应用程序与TCPIP协议的交互。,套接字通信模型,客户端,服务器,基于TCP/IP的网络,中间环节,套接字可以看成是两个网络应用
4、程序进行通信时,各自通信连接中的一个端点。如下图:,套接字中的信息通过驱动程序送入网卡,然后经网络发送到远端服务器,网卡将接收到的信息通过驱动程序送入套接字,进程C,进程S,套接字(Socket)分类,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW),打电话,在TCP/IP协议组中,使用TCP协议来实现流式套接字。,发信,在TCP/IP协议组中,使用UDP协议来实现数据报套接字。,该套接字允许对底层协议(如IP或ICMP)进行直接访问,常用来测试新安装的网络设备,以及对流经网卡的数据进行捕获分析。,它定义了一种无连接、不可靠的双向数据传
5、输服务。,它定义了一种可靠的、面向连接的双向数据传输服务。,2.字节顺序和Winsock的寻址方式,字节顺序含义:占内存多于一个字节类型的数据在内存中的存储顺序。通常有如下两种存储顺序:1 Little endian:将低序字节存储在起始地址(低序优先)2 Big endian:将高序字节存储在起始地址(高序优先),内存地址 1000 1001 1002 1003,低序优先存储顺序:0 x78 0 x56 0 x34 0 x12,高序优先存储顺序:0 x12 0 x34 0 x56 0 x78,然而处于主机上的数据却因不同的CPU上运行的操作系统的不同,字节顺序也不同,参见下表。,通常根据所处
6、的位置不同,低序优先字节顺序和高序优先字节顺序我们又分别称为主机字节顺序和网络字节顺序。,处理器 操作系统 字节排序HP-PA NT 低序优先HP-PA UNIX 高序优先Intelx86 全部 低序优先 Motorola680 x()全部 高序优先,因此,我们常说的主机字节顺序,就是低序优先,但主机上的字节顺序却不尽都是低序优先。,网络字节顺序是TCP/IP中规定的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。,不同字节顺序转换函数 主机字节顺序 hhost;网络字节顺序 nnetworku_short htons(u_short
7、 hostshort);把一个u_short 型的主机字节顺序存储的数转换为网络字节顺序存储字节数转换u_long htonl(u_long hostlong);把一个u_long型的主机字节顺序存储的数转换为网络字节顺序存储 字节数转换u_short ntohs(u_short netshort);把一个u_short 型的网络字节顺序存储的数转换为主机字节顺序存储字节数转换u_long ntohl(u_long netlong);把一个u_long型的网络字节顺序存储的数转换为主机字节顺序存储字节数转换,Winsock 寻址Winsock要兼容多个协议,所以必须使用通用的寻址方式。TCP/
8、IP(IP地址,端口)来指定一个地址,其它协议不一定如此。sockaddr结构,struct sockaddr u_short sa_family;/2个字节 共16位 char sa_data14;/14个字节;/共16个字节,sa_family:AF_UNIXUnix internal protocols AF_INETInternet protocols常用 本课程使用 AF_NSXerox NS protocols AF_IMPLINKIMP link layer其中,AF_ 代表“address family”sa_data 在不同的地址家族中存放的数据不同。,sockaddr_in
9、结构(Winsock定义的sockaddr结构的TCP/IP版本)本质和sockaddr是相同的结构(大小一致)sockaddr_in更容易操作。,struct sockaddr_in short sin_family;/Address family 2字节u_short sin_port;/16-bit port number 2字节struct in_addr sin_addr;/32-bit(IP)地址4字节char sin_zero 8;/unused 8字节;/共16个字节该结构与sockaddr兼容,供用户填入参数,sockaddr_in结构 成员说明。,sin_family:必须
10、设置为AF_INET,它告诉Winsock程序使用的是IP地址家族,sin_port:指定TCP或UDP通信服务的端口。0-1023:公共服务使用。如80为HTTP服务的端口 1024-65535:可以由普通用户使用。,struct in_addr sin_addr:IP地址。,sin_zero:为了和sockaddr保持一致。,in_addr结构 在in_addr中采用共用体类型。,struct in_addr union/共用体 struct u_char s_b1,s_b2,s_b3,s_b4;S_un_b;/1+1+1+1=4字节 struct u_short s_w1,s_w2;S_
11、un_w;/2+2=4字节 u_long S_addr;/4字节 S_un;struct in_addr sin_addr;/sockaddr_in结构中的IP地址,共用体:几个不同的变量共占一段内存的结构称为“共用体”。共用体变量所占的内存长度等于最长的成员的长度。这里共用体的三个变量长度一致。,点分 十进制记法,11000000 10101000 00000001 00001100,192.168.1.12,0 xC0,0 xA8,0 x01,0 x0C,IP地址设置,对地址进行设置:注意要把多字节数转换成网络字节顺序 假设有IP地址“192.168.1.12”4字节数据十进制表示 对于s
12、truct in_addr sin_addr可以有如下赋值方法:第一种方法(每个数都是单字节,不用转换)sin_addr.S_un.S_un_b.s_b1=192;sin_addr.S_un.S_un_b.s_b2=168;sin_addr.S_un.S_un_b.s_b3=1;sin_addr.S_un.S_un_b.s_b4=12;,第二种方法(转换成网络字节顺序 即高位在前)192 168 1 12 对应的16进制 0 xC0 0 xA8 0 x01 0 x0C 192 168 2字节16进制 0 xC0A8 1 12 2字节16进制 0 x010C sin_addr.S_un.S_un
13、_w.s_w1=htons(12*16*16*16+10*16+8);sin_addr.S_un.S_un_w.s_w2=htons(1*16*16+12);,第三种方法(转换成网络字节顺序 即高位在前)192.168.1.12 4字节16进制 0 xC0A8010C=htonl(12*pow(16,7)+10*pow(16,5)+8*pow(16,4)+1*pow(16,2)+12);,IP地址转换函数(点分十进制IP地址 网络字节顺序IP地址),char*inet_ntoa(struct in_addr in);把一个(Ipv4)32位网络字节顺序IP地址转换成”格式的字符串unsigne
14、d long inet_addr(const char*cp);把一个”格式的IP地址字符串转换为(Ipv4)32位网络字节顺序IP,因此可以有更简便的方法,也是最常用的方法=inet_addr(192.168.1.12);,struct sockaddr_in short sin_family;/Address family 2字节u_short sin_port;/16-bit port number 2字节struct in_addr sin_addr;/32-bit(IP)地址4字节char sin_zero 8;/unused 8字节;/共16个字节,下面初始化一个sockaddr_
15、in结构,sockaddr_in addrSrv;addrSrv.sin_family=AF_INET;/把16位主机字节转换为网络字节addrSrv.sin_port=htons(6789);/把点分制转换为32位网络字节=inet_addr(127.0.0.1);,总 结,套接字的基本概念套接字的通信模型Winsock的寻址方式主机字节顺序(低位在前)网络字节顺序(高位在前)两种顺序间的转换IP地址设置,3.Winsock API基本函数,Winsock API环境准备#include/包含了绝大部分socket函数和相关结构类型的声明#pragma comment(lib,WS2_32)
16、/链接到WS2_32.lib,打开WinsockWSAStartup()加载可用的Winsock 实现库函数形式int WSAStartup(WORD wVersionRequested,/传入参数 LPWSADATA lpWSAData/传出参数);/typedef unsigned short WORD;/2个字节 16位功能说明:检查系统中是否有可用的Winsock 实现库,并加载该实现库。网络应用程序开始必须调用此函数。,参数说明:,WORD wVersionRequested含义:用来指定想要加载的Winsock库的版本。表示一个字(2个字节)。高位字节指定副版本,低位字节制定主版本
17、。目前的Win32平台而言,Winsock2库的最新版本是2.2(Win95为Winsock1.1),参数设定:假设加载Winsock2.2版。指定此参数的值为0 x0202;wVersionRequested=0 x0202 或使用宏MAKEWORD(x,y):通过宏MAKEWORD来指定 参数的值。x是高位字节,y是低位字节 MAKEWORD(2,2)指定版本为Winsock2.2版,typedef struct WSAData WORD wVersion;/调用者希望使用的版本号 WORD wHighVersion;/库文件支持的最高版本 char szDescriptionWSADES
18、CRIPTION_LEN+1;/Winsock库描述字符串 如 Winsock2.0库 char szSystemStatusWSASYS_STATUS_LEN+1;/系统状态字符串 如:Running unsigned short iMaxSockets;/Winsock2库已废弃参数 unsigned short iMaxUdpDg;/Winsock2库已废弃参数 char*lpVendorInfo;/Winsock2库已废弃参数 WSADATA,*LPWSADATA;,LPWSADATA lpWSAData 一个指向WSADATA结构的指针,用来返回加载库的详细信息。,WSADATA*l
19、pWSAData;等价于 LPWSADATA lpWSAData;,返回0则正确,否则返回错误。错误代码可以通过WSAGetLastError()来获取。下面只举几个例子说明。更多信息可以MSDN获取,也可到winsock.h或 winsock2.h中查找。如:WSASYSNOTREADY:10091 加载的Winsock 库不存在 WSAEFAULT:10014 lpWSAData参数是无效的指针,返回值:,终止使用WinsockWSACleanup()函数形式:int WSACleanup();功能说明:该函数终止应用程序对Winsock 库的使用,释放加载的Winsock库。每一个WSA
20、Startup的调用必须对应一个WSACleanup的调用。返回值:调用成功返回0;否则SOCKET_ERROR被返回,具体错误可以通过函数 WSAGetLastError()来获取。SOCKET_ERROR是系统宏定义值为-1。,#include/标准输入输出系统文件#include/winsock声明文件#pragma comment(lib,WS2_32)/链接到WS2_32.libvoid main()/通过载入Winsock库,来使用Winsock的相关函数 WSADATA wsaData;/用来返回Winsock库的详细信息 WORD version=MAKEWORD(2,2);/
21、wVersionRequested=0 x0202;int ret=WSAStartup(version,加载释放举例:,WSADATA,/*进行版本号匹配的检查*/if(LOBYTE(wsaData.wVersion)!=2|/取低位字节 主版本 HIBYTE(wsaData.wVersion)!=2)/取高位字节 幅版本 printf(Winsock库版本不匹配n);WSACleanup();/释放库return;printf(“wVersion=%dn”,wsaData.wVersion);/希望使用版本printf(“wHighVersion=%dn”,wsaData.wHighVer
22、sion);/最高版本 printf(“szDescription=%sn”,wsaData.szDescription);/库描述printf(“szSystemStatus=%sn”,wsaData.szSystemStatus);/系统状态 WSACleanup();/释放库,wVersion=514wHighVersion=514szDescription=WinSock 2.0szSystemStatus=Running,514说明版本号是2.2 0 x0202:十进制 21616+2=514WinSock 2.0指 WinSock 2库,WSADATA,创建套接字socket(),
23、函数形式:SOCKET socket(int af,/说明套接字使用的协议地址族 int type,/描述套接字的协议类型 int protocol/说明套接字使用的特定协议字段);,为应用程序创建套接字,返回值SOCKET:系统提供的类型定义 typedef u_int SOCKET;调用成功:返回新创建的套接字描述符(一个编号)。调用失败:返回INVALID_SOCKET(系统宏定义值0)。可以调用WSAGetLastError()来获取具体错误的代码。创建套接字后系统会为其分配相应的系统缓冲区。,举例说明:流式和数据报套接字中协议字段指定0时,取缺省的协议SOCKET sockSrv=s
24、ocket(AF_INET,SOCK_STREAM,IPPROTO_TCP);SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);/等同上一行 SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);/等同上一行 SOCKET sockSrv=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);SOCKET sockSrv=socket(AF_INET,SOCK_RAW,IPPROTO_IP);
25、,关闭套接字closesocket(),函数形式:int closesocket(SOCKET s);,关闭一个不再使用的套接字。,调用成功:返回0;调用失败:返回SOCKET_ERROR(系统宏定义,值为-1)具体错误代码:调用WSAGetLastError()来获取。,绑定套接字到指定的Socket地址bind(),函数形式:int bind(SOCKET s,const struct sockaddr*name,/Socket地址 int namelen/指定地址参数(name)的长度);,把一个套接字与一个Socket地址联系起来。,调用成功返回0,否则将返回SOCKET_ERROR,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Winsock 编程 接口
![提示](https://www.31ppt.com/images/bang_tan.gif)
链接地址:https://www.31ppt.com/p-6523775.html