基于TCP(UDP)的网络socket_编程_第1页
基于TCP(UDP)的网络socket_编程_第2页
基于TCP(UDP)的网络socket_编程_第3页
基于TCP(UDP)的网络socket_编程_第4页
基于TCP(UDP)的网络socket_编程_第5页
已阅读5页,还剩72页未读 继续免费阅读

下载本文档

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

文档简介

1、北京交通大学出版社北京交通大学出版社 基于基于TCP(UDP) 的的 网络安全(网络安全(socket) 编程编程北京交通大学出版社北京交通大学出版社1.1.套接字套接字(socket)(socket)的引入的引入为了能够方便的开发网络应用软件,由美国伯克利大学在为了能够方便的开发网络应用软件,由美国伯克利大学在UnixUnix上推出了一种应用程序访问通信协议的操作系统调用上推出了一种应用程序访问通信协议的操作系统调用socket(socket(套接字套接字) )。socketsocket的出现,使程序员可以很方便地访问的出现,使程序员可以很方便地访问TCP/IPTCP/IP,从而开发各种网络

2、应用的程序。,从而开发各种网络应用的程序。随着随着UnixUnix的应用推广,套接字在编写网络软件中得到了极大的应用推广,套接字在编写网络软件中得到了极大的普及。后来,套接字又被引进了的普及。后来,套接字又被引进了WindowsWindows等操作系统,成为开等操作系统,成为开发网络应用程序的非常有效快捷的工具。发网络应用程序的非常有效快捷的工具。套接字存在于通信区域中。通信区域也叫地址族套接字存在于通信区域中。通信区域也叫地址族,它是一个,它是一个抽象的概念,抽象的概念,主要用于将通过套接字通信的进程的共有特性综合主要用于将通过套接字通信的进程的共有特性综合在一起。在一起。套接字通常只与同一

3、区域的套接字交换数据(也有可能套接字通常只与同一区域的套接字交换数据(也有可能跨区域通信,但这只在执行了某种转换进程后才能实现)。跨区域通信,但这只在执行了某种转换进程后才能实现)。Windows SocketsWindows Sockets只支持一个通信区域:只支持一个通信区域:网际域网际域( ( AF_INETAF_INET) ),这个域被使用网际协议簇通信的,这个域被使用网际协议簇通信的进程使用。进程使用。北京交通大学出版社北京交通大学出版社2.2.网络字节顺序网络字节顺序不同的计算机存放多字节值的顺序不同,有的机器在起始地不同的计算机存放多字节值的顺序不同,有的机器在起始地址存放低位字

4、节址存放低位字节( (低位先存低位先存) ),有的机器在起始地址存放高位字节,有的机器在起始地址存放高位字节( (高位先存高位先存) )。基于基于IntelIntel的的CPUCPU,即我们常用的,即我们常用的PCPC机采用的是低位先存。为机采用的是低位先存。为保证数据的正确性,在网络协议中需要指定网络字节顺序。保证数据的正确性,在网络协议中需要指定网络字节顺序。TCP/IPTCP/IP协议使用协议使用1616位整数和位整数和3232位整数的高位先存格式位整数的高位先存格式。北京交通大学出版社北京交通大学出版社客户机服务器模式客户机服务器模式1)1)在在TCP/IPTCP/IP网络应用中,通信

5、的两个进程间相互作用的主要网络应用中,通信的两个进程间相互作用的主要模式是客户机模式是客户机/ /服务器模式服务器模式(client/server)(client/server),即客户向服务器提,即客户向服务器提出请求,服务器接收到请求后,提供相应的服务。出请求,服务器接收到请求后,提供相应的服务。2)2)客户机客户机/ /服务器模式的建立基于以下两点:首先,建立网服务器模式的建立基于以下两点:首先,建立网络的起因是网络中软硬件资源、运算能力和信息不均等,需要共络的起因是网络中软硬件资源、运算能力和信息不均等,需要共享,从而造就拥有众多资源的主机提供服务,资源较少的客户请享,从而造就拥有众多

6、资源的主机提供服务,资源较少的客户请求服务这一非对等作用。其次,网间进程通信完全是异步的,相求服务这一非对等作用。其次,网间进程通信完全是异步的,相互通信的进程间既不存在父子关系,又不共享内存缓冲区,因此互通信的进程间既不存在父子关系,又不共享内存缓冲区,因此需要一种机制为希望通信的进程间建立联系,为二者的数据交换需要一种机制为希望通信的进程间建立联系,为二者的数据交换提供同步,这就是基于客户机提供同步,这就是基于客户机/ /服务器模式的服务器模式的TCP/IPTCP/IP。北京交通大学出版社北京交通大学出版社客户机服务器模式客户机服务器模式客户机客户机/ /服务器模式在操作过程中采取的是主动

7、请求的方式。服务器模式在操作过程中采取的是主动请求的方式。 首先服务器方要先启动首先服务器方要先启动,并根据请求提供相应的服务:,并根据请求提供相应的服务:打开一个通信通道并告知本地主机,它愿意在某一地址和端口上打开一个通信通道并告知本地主机,它愿意在某一地址和端口上接收客户请求。接收客户请求。等待客户请求到达该端口。等待客户请求到达该端口。接收到重复服务请求,处理该请求并发送应答信号。接收到并发接收到重复服务请求,处理该请求并发送应答信号。接收到并发服务请求,要激活一个新的进程服务请求,要激活一个新的进程( (或线程或线程) )来处理这个客户请求。来处理这个客户请求。新进程新进程( (或线程

8、或线程) ) 处理此客户请求,并不需要对其它请求作出应处理此客户请求,并不需要对其它请求作出应答。服务完成后,关闭此新进程与客户的通信链路,并终止。答。服务完成后,关闭此新进程与客户的通信链路,并终止。返回第二步,等待另一客户请求。返回第二步,等待另一客户请求。关闭服务器。关闭服务器。 客户方:客户方:打开一个通信通道,并连接到服务器所在主机的特定端口。打开一个通信通道,并连接到服务器所在主机的特定端口。向服务器发服务请求报文,等待并接收应答;继续提出请求。向服务器发服务请求报文,等待并接收应答;继续提出请求。请求结束后关闭通信通道并终止。请求结束后关闭通信通道并终止。北京交通大学出版社北京交

9、通大学出版社Windows SocketsWindows Sockets的实现的实现Windows SocketsWindows Sockets是是Microsoft WindowsMicrosoft Windows的网络程序设计接口,的网络程序设计接口,它是从它是从Berkeley SocketsBerkeley Sockets扩展而来的,以动态链接库的形式提供扩展而来的,以动态链接库的形式提供给我们使用。给我们使用。Windows SocketsWindows Sockets在继承了在继承了Berkeley SocketsBerkeley Sockets主要主要特征的基础上,又对它进行了重

10、要扩充。这些扩充主要是提供了特征的基础上,又对它进行了重要扩充。这些扩充主要是提供了一些异步函数,并增加了符合一些异步函数,并增加了符合WindowsWindows消息驱动特性的网络事件消息驱动特性的网络事件异步选择机制。异步选择机制。Windows Sockets 1.1Windows Sockets 1.1和和Berkeley SocketsBerkeley Sockets都是基于都是基于TCP/IPTCP/IP协议的;协议的;Windows Sockets 2Windows Sockets 2从从Windows Sockets 1.1Windows Sockets 1.1发展而来,发展而

11、来,与协议无关并向下兼容,可以使用任何底层传输协议提供的通信与协议无关并向下兼容,可以使用任何底层传输协议提供的通信能力,来为上层应用程序完成网络数据通讯,而不关心底层网络能力,来为上层应用程序完成网络数据通讯,而不关心底层网络链路的通讯情况,真正实现了底层网络通讯对应用程序的透明。链路的通讯情况,真正实现了底层网络通讯对应用程序的透明。北京交通大学出版社北京交通大学出版社套接字的类型套接字的类型1)1)流式套接字流式套接字(SOCK_STREAMSOCK_STREAM)提供面向连接、可靠的数据传输服务,数据无差错、无重复提供面向连接、可靠的数据传输服务,数据无差错、无重复的发送,且按发送顺序

12、接收。的发送,且按发送顺序接收。2)2)数据报式套接字数据报式套接字(SOCK_DGRAMSOCK_DGRAM)提供无连接服务。数据包以独立包形式发送,不提供无错保提供无连接服务。数据包以独立包形式发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。证,数据可能丢失或重复,并且接收顺序混乱。3)3)原始套接字原始套接字(SOCK_RAWSOCK_RAW)北京交通大学出版社北京交通大学出版社网络安全编程基本函数网络安全编程基本函数北京交通大学出版社北京交通大学出版社1 1、SOCKETSOCKET类型类型SOCKET是socket套接字类型,在WINSOCK2.H中有如下定义:typed

13、ef unsigned int u_int;typedef u_int SOCKET;可知套接字实际上就是一个无符号整型,它将被Socket环境管理和使用。套接字的使用流程:被创建、设置、用来发送和接收数据,最后会被关闭。 北京交通大学出版社北京交通大学出版社2 WORD2 WORD类型、类型、MAKEWORDMAKEWORD、LOBYTELOBYTE和和HIBYTEHIBYTE宏宏WORDWORD类型是一个类型是一个1616位的无符号整型位的无符号整型,在,在WTYPES.HWTYPES.H中被定义为:中被定义为:typedef unsigned short typedef unsigned

14、 short WORDWORD; ;目的目的: :是提供两个字节的存储,在是提供两个字节的存储,在SocketSocket中这两个字节可以表示主版本号和副中这两个字节可以表示主版本号和副版本号。使用版本号。使用MAKEWORDMAKEWORD宏可以给一个宏可以给一个WORDWORD类型赋值。类型赋值。例如例如: :要表示主版本号要表示主版本号2 2,副版本号,副版本号0 0,可以使用以下代码:,可以使用以下代码:WORD wVersionRequested;WORD wVersionRequested;wVersionRequested = MAKEWORD( 2, 0 ); wVersion

15、Requested = MAKEWORD( 2, 0 ); 注意低位内存存储主版本号注意低位内存存储主版本号2 2,高位内存存储副版本号,高位内存存储副版本号0 0,其值为,其值为0 x00020 x0002。使用宏使用宏LOBYTELOBYTE可以读取可以读取WORDWORD的低位字节,的低位字节,HIBYTEHIBYTE可以读取高位字节。可以读取高位字节。北京交通大学出版社北京交通大学出版社3 WSAStartup ()3 WSAStartup ()函数函数WSAStartupWSAStartup函数被用来函数被用来初始化初始化SocketSocket环境环境,它的定义如下:,它的定义如下

16、:int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);返回值返回值: :整型整型; ;若返回值为若返回值为0 0,则初始化成功,若不为,则初始化成功,若不为0 0则失败。则失败。调用方式调用方式: :PASCALPASCAL(即标准类型,(即标准类型,PASCALPASCAL等于等于_stdcall_stdcall)参数参数: :第一个参数为第一个参数为WORDWORD

17、类型,指明了类型,指明了SocketSocket的版本号的版本号第二个参数为第二个参数为WSADATAWSADATA类型的指针。类型的指针。北京交通大学出版社北京交通大学出版社4 WSADATA4 WSADATA类型和类型和LPWSADATALPWSADATA类型类型WSADATAWSADATA类型是一个结构,描述了类型是一个结构,描述了SocketSocket库的一些相关信息库的一些相关信息,其结构定,其结构定义如下:义如下:typedef struct typedef struct WSADataWSAData WORD wVersion; WORD wVersion; WORD wHig

18、hVersion; WORD wHighVersion; char szDescriptionWSADESCRIPTION_LEN+1; char szDescriptionWSADESCRIPTION_LEN+1; char szSystemStatusWSASYS_STATUS_LEN+1; char szSystemStatusWSASYS_STATUS_LEN+1; unsigned short iMaxSockets; unsigned short iMaxSockets; unsigned short iMaxUdpDg; unsigned short iMaxUdpDg; cha

19、r FAR char FAR * * lpVendorInfo; lpVendorInfo; WSADATAWSADATA; ;typedef WSADATA FAR typedef WSADATA FAR * *LPWSADATALPWSADATA; ;wVersion:wVersion:存储了存储了SocketSocket的版本类型。的版本类型。LPWSADATA:LPWSADATA:是是WSADATAWSADATA的指针类型。的指针类型。它们不用程序员手动填写,而是通过它们不用程序员手动填写,而是通过SocketSocket的初始化函数的初始化函数WSAStartupWSAStartup

20、读读取出来。取出来。北京交通大学出版社北京交通大学出版社5 socket ()5 socket ()函数函数socketsocket的创建函数,其定义为:的创建函数,其定义为:SOCKET PASCAL FAR socket (int af, int type, int protocol);SOCKET PASCAL FAR socket (int af, int type, int protocol);int af:int af:代表网络地址族,目前只有一种取值是有效的,即代表网络地址族,目前只有一种取值是有效的,即AF_INETAF_INET,代表代表internetinternet地址族

21、;地址族;int type:int type:代表网络协议类型,代表网络协议类型,SOCK_DGRAMSOCK_DGRAM代表代表UDPUDP协议,协议,SOCK_STREAMSOCK_STREAM代表代表TCPTCP协议;协议;int protocol:int protocol:指定网络地址族的特殊协议,目前无用,赋值指定网络地址族的特殊协议,目前无用,赋值0 0即可。即可。创建成功则返回值为创建成功则返回值为SOCKETSOCKET,若返回,若返回INVALID_SOCKETINVALID_SOCKET则失败。则失败。北京交通大学出版社北京交通大学出版社6 bind () ()函数函数in

22、t bind( SOCKET int bind( SOCKET s s, const struct sockaddr FAR , const struct sockaddr FAR * *namename, int , int namelen namelen ););参数:参数:s s:指定要绑定的套接字指定要绑定的套接字 const struct sockaddr FAR const struct sockaddr FAR * *namename:了该套接字的本地地址信息,是指向了该套接字的本地地址信息,是指向sockaddrsockaddr结构的指针变结构的指针变量,由于该地址结构是为所有

23、的地址家族准备的,这个结构可能量,由于该地址结构是为所有的地址家族准备的,这个结构可能(通常会)随所使用的网络协议不同而不同(通常会)随所使用的网络协议不同而不同Namelen:Namelen:指定该地址结构的长度。指定该地址结构的长度。北京交通大学出版社北京交通大学出版社6 bind () ()函数函数int bind( SOCKET int bind( SOCKET s s, const struct , const struct sockaddrsockaddr FAR FAR * *namename, int , int namelen namelen ););sockaddrsock

24、addr结构定义如下:结构定义如下: struct sockaddr struct sockaddr u_short sa_family; u_short sa_family; char sa_data14; char sa_data14; ; ; sa_family:sa_family:指定该地址家族,在这里必须设为指定该地址家族,在这里必须设为AF_INETAF_INET。sa_data:sa_data:仅仅是表示要求一块内存分配区,起到占位的作用,该区域仅仅是表示要求一块内存分配区,起到占位的作用,该区域中指定与协议相关的具体地址信息。由于实际要求的只是内存区,中指定与协议相关的具体地址

25、信息。由于实际要求的只是内存区,所以对于不同的协议家族,用不同的结构来替换所以对于不同的协议家族,用不同的结构来替换sockaddrsockaddr。除了。除了sa_familysa_family外,外,sockaddrsockaddr是按网络字节顺序表示的。在是按网络字节顺序表示的。在TCP/IPTCP/IP中,中,我们可以用我们可以用sockaddr_insockaddr_in结构替换结构替换sockaddrsockaddr,以方便我们填写地,以方便我们填写地址信息。址信息。 北京交通大学出版社北京交通大学出版社续:sockaddr_in的定义如下:的定义如下: struct sockad

26、dr_in short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero8; ; 其中,其中,sin_family表示地址族,对于表示地址族,对于IP地址,地址,sin_family成员将一直是成员将一直是AF_INET。成员成员sin_port指定的是将要分配给套接字的端口。成员指定的是将要分配给套接字的端口。成员sin_addr给出的是套接字的主机给出的是套接字的主机IP地址。而成员地址。而成员sin_zero只是一个填充数,以使只是一个填充数,以使sockaddr_in结构和结构和soc

27、kaddr结构的长结构的长度一样。如果这个函数调用成功,它将返回度一样。如果这个函数调用成功,它将返回0。如果调用失败,这个函数就会返回一。如果调用失败,这个函数就会返回一个个SOCKET_ERROR,错误信息可以通过,错误信息可以通过WSAGetLastError函数返回。函数返回。 将将IP地址指定为地址指定为INADDR_ANY,允许套接字向任何分配给本地机器的,允许套接字向任何分配给本地机器的IP地址发送地址发送或接收数据。多数情况下,每个机器只有一个或接收数据。多数情况下,每个机器只有一个IP地址,但有的机器可能会有多个网卡,地址,但有的机器可能会有多个网卡,每个网卡都可以有自己的每

28、个网卡都可以有自己的IP地址,用地址,用INADDR_ANY可以简化应用程序的编写。将地可以简化应用程序的编写。将地址指定为址指定为INADDR_ANY,允许一个独立应用接受发自多个接口的回应。如果我们只,允许一个独立应用接受发自多个接口的回应。如果我们只想让套接字使用多个想让套接字使用多个IP中的一个地址,就必须指定实际地址,要做到这一点,可以用中的一个地址,就必须指定实际地址,要做到这一点,可以用inet_addr()函数,这个函数需要一个字符串作为其参数,该字符串指定了以点分十进函数,这个函数需要一个字符串作为其参数,该字符串指定了以点分十进制格式表示的制格式表示的IP地址地址(如如19

29、2.168.0.16)。而且。而且inet_addr()函数会返回一个适合分配给函数会返回一个适合分配给S_addr的的u_long类型的数值。类型的数值。inet_ntoa()函数会完成相反的转换,它接受一个函数会完成相反的转换,它接受一个in_addr结构体类型的参数并返回一个以点分十进制格式表示的结构体类型的参数并返回一个以点分十进制格式表示的IP地址字符串。地址字符串。北京交通大学出版社北京交通大学出版社7 setsockopt ()7 setsockopt ()函数函数这个函数用来这个函数用来设置设置SocketSocket的属性的属性,若不能正确设置,若不能正确设置socketso

30、cket属性,则数据属性,则数据的发送和接收会失败。定义如下:的发送和接收会失败。定义如下:int PASCAL FAR setsockopt (SOCKET s, int level, int optname,int PASCAL FAR setsockopt (SOCKET s, int level, int optname, const char FAR const char FAR * * optval, int optlen); optval, int optlen);返回值返回值: :intint类型,类型,0 0代表成功,代表成功,SOCKET_ERRORSOCKET_ERROR

31、代表有错误发生代表有错误发生。SOCKET sSOCKET s:代表要设置的套接字;代表要设置的套接字;int levelint level:代表要设置的属性所处的层次,层次包含以下取值:代表要设置的属性所处的层次,层次包含以下取值:SOL_SOCKETSOL_SOCKET代表套代表套接字层次;接字层次;IPPROTO_TCPIPPROTO_TCP代表代表TCPTCP协议层次,协议层次,IPPROTO_IPIPPROTO_IP代表代表IPIP协议层次(后协议层次(后面两个我都没有用过);面两个我都没有用过);int optnameint optname:代表设置参数的名称,代表设置参数的名称,

32、SO_BROADCASTSO_BROADCAST代表允许发送广播数据的属性,其代表允许发送广播数据的属性,其它属性可参考它属性可参考MSDNMSDN;const char FAR const char FAR * * optval optval:代表指向存储参数数值的指针,注意这里可能要使用代表指向存储参数数值的指针,注意这里可能要使用reinterpret_castreinterpret_cast类型转换;类型转换;int optlenint optlen:代表存储参数数值变量的长度。代表存储参数数值变量的长度。北京交通大学出版社北京交通大学出版社8 8 sockaddr_insockadd

33、r_in、in_addrin_addr类型,类型,inet_addrinet_addr、inet_ntoainet_ntoa函数函数sockaddr_insockaddr_in定义了定义了socketsocket发送和接收数据包的地址发送和接收数据包的地址,定义如下:,定义如下:struct struct sockaddr_in sockaddr_in short sin_family; short sin_family; u_short sin_port; u_short sin_port; struct in_addrstruct in_addr sin_addrsin_addr; ; c

34、har sin_zero8; char sin_zero8;其中其中in_addrin_addr的定义如下:的定义如下:struct struct in_addrin_addr union struct u_char s_b1,s_b2,s_b3,s_b4; union struct u_char s_b1,s_b2,s_b3,s_b4; S_un_b;S_un_b; struct u_short s_w1,s_w2; S_un_w; struct u_short s_w1,s_w2; S_un_w; u_long u_long S_addrS_addr; ; S_unS_un; ;北京交通大

35、学出版社北京交通大学出版社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; S_un;首先阐述首先阐述in_addrin_addr的含义,很显然它是一个存储的含义,很显然它是一个存储ipip地址的联地址的联合体,有三种表达方式:合体,有三种表达方式:第一种:用四个字节来表示第一种:用四个字节来表示IPIP地址的四个数字;地址的四个数字;第二种:用两个双字节来表示第二种:用两个双字节来表示IPIP地址;地址;第三种:用一个长

36、整型来表示第三种:用一个长整型来表示IPIP地址。地址。给给in_addrin_addr赋值的一种最简单方法是使用赋值的一种最简单方法是使用inet_addrinet_addr函数,它函数,它可以可以把一个代表把一个代表IPIP地址的字符串赋值转换为地址的字符串赋值转换为in_addrin_addr类型类型,如,如addrto.sin_addr.s_addr=inet_addr(192.168.0.2);addrto.sin_addr.s_addr=inet_addr(192.168.0.2);其反函数是其反函数是inet_inet_n ntotoa()a():network to ascii

37、 将网络地址转换成将网络地址转换成“.”.”点隔的字符串格式,即把一个点隔的字符串格式,即把一个in_addrin_addr类型转换为一个字符串。类型转换为一个字符串。北京交通大学出版社北京交通大学出版社struct sockaddr_in short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero8;sockaddr_insockaddr_in的含义比的含义比in_addrin_addr的含义要广泛,其各个字段的含义和取值如下:的含义要广泛,其各个字段的含义和取值如下:short sin_familys

38、hort sin_family:代表网络地址族,如前所述,只能取值代表网络地址族,如前所述,只能取值AF_INETAF_INET;u_short sin_portu_short sin_port:代表代表IPIP地址端口,由程序员指定;地址端口,由程序员指定;struct in_addr sin_addrstruct in_addr sin_addr:代表代表IPIP地址;地址;char sin_zero8char sin_zero8:是为了保证是为了保证sockaddr_insockaddr_in与与SOCKADDRSOCKADDR类型的长度相等而填充进来的字段。类型的长度相等而填充进来的字

39、段。北京交通大学出版社北京交通大学出版社程序示例:程序示例:以下代表指明了广播地址,端口号为以下代表指明了广播地址,端口号为78617861的一个地址:的一个地址: sockaddr_in addrto; sockaddr_in addrto; /发往的地址发往的地址 memset(&addrto,0,sizeof(addrto);memset(&addrto,0,sizeof(addrto); addrto. addrto.sin_familysin_family = AF_INET; = AF_INET; /地址类型为地址类型为internetworkinternetwor

40、k addrto. addrto.sin_addr.s_addrsin_addr.s_addr = INADDR_BROADCAST; = INADDR_BROADCAST; /设置设置ipip为广播地址为广播地址 addrto.addrto.sin_port sin_port = htons(7861); = htons(7861); /端口号为端口号为78617861北京交通大学出版社北京交通大学出版社9 sockaddr ()9 sockaddr ()类型类型sockaddrsockaddr类型是用来表示类型是用来表示SocketSocket地址的类型,同上面的地址的类型,同上面的soc

41、kaddr_insockaddr_in类类型相比,型相比,sockaddrsockaddr的适用范围更广,因为的适用范围更广,因为sockaddr_insockaddr_in只适用于只适用于TCP/IPTCP/IP地址。地址。SockaddrSockaddr的定义如下:的定义如下:struct sockaddr struct sockaddr u_short sa_family;u_short sa_family; char sa_data14;char sa_data14; ; 可知可知sockaddrsockaddr有有1616个字节,而个字节,而sockaddr_insockaddr_i

42、n也有也有1616个字节,所以个字节,所以sockaddr_insockaddr_in是可以强制类型转换为是可以强制类型转换为sockaddrsockaddr的。事实上也往往使用这种方法。的。事实上也往往使用这种方法。北京交通大学出版社北京交通大学出版社10 Sleep ()10 Sleep ()函数函数线程挂起函数,表示线程挂起一段时间。线程挂起函数,表示线程挂起一段时间。Sleep(1000)Sleep(1000)表示表示挂起一秒。定义于挂起一秒。定义于WINBASE.HWINBASE.H头文件中。头文件中。WINBASE.HWINBASE.H又被包含于又被包含于WINDOWS.HWIND

43、OWS.H中,然后中,然后WINDOWS.HWINDOWS.H被被WINSOCK2.HWINSOCK2.H包含。包含。所以使用所以使用SleepSleep函数不需要包含其它头文件。函数不需要包含其它头文件。北京交通大学出版社北京交通大学出版社11 sendto()11 sendto()函数函数在在SocketSocket中有两套发送和接收函数,一是中有两套发送和接收函数,一是sendtosendto和和recvfromrecvfrom;二是;二是sendsend和和recvrecv。前一套在函数参数中要指明地址;而后一套需要先。前一套在函数参数中要指明地址;而后一套需要先将套接字和一个地址绑定

44、,然后直接发送和接收,不需绑定地址。将套接字和一个地址绑定,然后直接发送和接收,不需绑定地址。sendtosendto的定义如下:的定义如下:int PASCAL FAR sendto (SOCKET s, const char FAR int PASCAL FAR sendto (SOCKET s, const char FAR * * buf, int buf, int len, int flags, const struct sockaddr FAR len, int flags, const struct sockaddr FAR * *to, int to, int tolen);t

45、olen);第一个参数就是套接字;第一个参数就是套接字;第二个参数是要传送的数据指针;第二个参数是要传送的数据指针;第三个参数是要传送的数据长度(字节数);第三个参数是要传送的数据长度(字节数);第四个参数是传送方式的标识,如果不需要特殊要求则可以设置为第四个参数是传送方式的标识,如果不需要特殊要求则可以设置为0 0,其它值请参考,其它值请参考MSDNMSDN;第五个参数是目标地址,注意这里使用的是第五个参数是目标地址,注意这里使用的是sockaddrsockaddr的指针;的指针;第六个参数是地址的长度;第六个参数是地址的长度;返回值为整型,如果成功,则返回发送的字节数,失败则返回返回值为整

46、型,如果成功,则返回发送的字节数,失败则返回SOCKET_ERRORSOCKET_ERROR。北京交通大学出版社北京交通大学出版社12 WSAGetLastError()12 WSAGetLastError()函数函数该函数用来在该函数用来在SocketSocket相关相关APIAPI失败后读取错误码,根据这些失败后读取错误码,根据这些错误码可以对照查出错误原因。错误码可以对照查出错误原因。13 closesocket()13 closesocket()函数函数关闭套接字,其参数为关闭套接字,其参数为SOCKETSOCKET类型。成功返回类型。成功返回0 0,失败返回,失败返回SOCKET_E

47、RRORSOCKET_ERROR。 北京交通大学出版社北京交通大学出版社14 WSACleanup ()14 WSACleanup ()函数函数卸载卸载SocketSocket库,释放系统资源。库,释放系统资源。返回值为返回值为0 0表示成功,表示成功,SOCKET_ERRORSOCKET_ERROR表示失败。表示失败。北京交通大学出版社北京交通大学出版社下面是一个用下面是一个用UDPUDP发送广播报文的程序示例发送广播报文的程序示例:#include #include void main() SOCKET sock; /socket套接字套接字 char szMsg = this is a

48、UDP test package;/被发送的字段被发送的字段 /1./1.启动启动SOCKETSOCKET库,版本为库,版本为2.02.0 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( 0 != err ) /检查检查Socket初始化是否成功初始化是否成功 coutSocket2.0初始化失败,初始化失败,Exit!; return; /检查检查So

49、cket库的版本是否为库的版本是否为2.0 if (LOBYTE( wsaData.wVersion ) != 2 | HIBYTE( wsaData.wVersion ) != 0 ) WSACleanup( ); return; 北京交通大学出版社北京交通大学出版社/2./2.创建创建socketsocket, sock = socket(sock = socket( AF_INET, /internetwork: UDP, TCP, etc AF_INET, /internetwork: UDP, TCP, etc SOCK_DGRAM, /SOCK_DGRAM SOCK_DGRAM,

50、/SOCK_DGRAM说明是说明是UDPUDP类型类型 0 /protocol0 /protocol ); ); if (INVALID_SOCKET = sock ) if (INVALID_SOCKET = sock ) coutSocket coutSocket 创建失败,创建失败,Exit!;Exit!; return; return; /3. /3.设置该套接字为广播类型,设置该套接字为广播类型, bool opt = true;bool opt = true; setsockopt(sock, SOL_SOCKET, SO_BROADCAST, reinterpret_castch

51、ar FAR setsockopt(sock, SOL_SOCKET, SO_BROADCAST, reinterpret_cast(&opt), sizeof(opt);(&opt), sizeof(opt); /4. /4.设置发往的地址设置发往的地址 sockaddr_in addrto; /sockaddr_in addrto; /发往的地址发往的地址 memset(&addrto,0,sizeof(addrto);memset(&addrto,0,sizeof(addrto); addrto.sin_family = AF_INET; / addrto

52、.sin_family = AF_INET; /地址类型为地址类型为internetworkinternetwork addrto.sin_addr.s_addr = INADDR_BROADCAST; / addrto.sin_addr.s_addr = INADDR_BROADCAST; /设置设置ipip为广播地址为广播地址 addrto.sin_port = htons(7861); /addrto.sin_port = htons(7861); /端口号为端口号为78617861 int nlen=sizeof(addrto); int nlen=sizeof(addrto); un

53、signed int uIndex = 1; unsigned int uIndex = 1; 北京交通大学出版社北京交通大学出版社while(true)while(true) Sleep(1000); / Sleep(1000); /程序休眠一秒程序休眠一秒 /向广播地址发送消息向广播地址发送消息 if( sendto(sock, szMsg, strlen(szMsg), 0, if( sendto(sock, szMsg, strlen(szMsg), 0, (sockaddr(sockaddr* *)&addrto,nlen)&addrto,nlen) = SOCKET

54、_ERROR ) = SOCKET_ERROR ) coutWSAGetLastError()endl; coutWSAGetLastError()endl; else else coutuIndex+:an UDP package is sended.endl; coutuIndex+:an UDP package is sended.-设置设置-链接链接-对象对象/ /库模块库模块 3 3WINSOCK.DLLWINSOCK.DLL: : WINSOCKWINSOCK的动态连接库,位于的动态连接库,位于WINDOWSWINDOWS的安装目录下。的安装目录下。北京交通大学出版社北京交通大学出

55、版社服务器端操作服务器端操作 socketsocket(套接字)(套接字)1)1)在初始化阶段调用在初始化阶段调用WSAStartup()WSAStartup() 此函数在应用程序中初始化此函数在应用程序中初始化Windows Sockets DLL Windows Sockets DLL ,只有此函数调用成功后,应用程序才可以再调用其他只有此函数调用成功后,应用程序才可以再调用其他Windows Sockets DLLWindows Sockets DLL中的中的APIAPI函数。函数。在程式中调用该函数的形式如下:在程式中调用该函数的形式如下: int int WSAStartupWSAS

56、tartup(WORD wVersionRequested,LPWSADATA lpWSAData);(WORD wVersionRequested,LPWSADATA lpWSAData);北京交通大学出版社北京交通大学出版社int int WSAStartupWSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);(WORD wVersionRequested,LPWSADATA lpWSAData);wVersionRequestedwVersionRequested:用于指定准备加载的用于指定准备加载的WinsockWinsock库

57、的版本。库的版本。高位字节指定所需要的高位字节指定所需要的WinsockWinsock库的副版本,而低库的副版本,而低位字节则是主版本。位字节则是主版本。可用可用MAKEWORD(x,y)(MAKEWORD(x,y)(其中,其中,x x是高位字节是高位字节,y y是低位是低位字节字节) )方便地获得方便地获得wVersionRequestedwVersionRequested的正确值。的正确值。 lpWSADatalpWSAData:是指向是指向WSADATAWSADATA结构的指针,用来存储系统传回的结构的指针,用来存储系统传回的关于加载的库版本的资料,是一个结构体。关于加载的库版本的资料,

58、是一个结构体。北京交通大学出版社北京交通大学出版社2)2)建立建立SocketSocket 初始化初始化WinSockWinSock的动态连接库后,需要在服务器端建立一个监的动态连接库后,需要在服务器端建立一个监听的听的SocketSocket,为此可以调用,为此可以调用Socket()Socket()函数用来建立这个监听的函数用来建立这个监听的SocketSocket,并定义此,并定义此SocketSocket所使用的通信协议。所使用的通信协议。定义方式:定义方式:SOCKETSOCKET PASCAL FAR PASCAL FAR socketsocket(int af, int type

59、, int protocol)(int af, int type, int protocol)参数参数: : afaf: :address familyaddress family,目前只提供,目前只提供AF_INET(PAF_INET(PF_INET)F_INET); typetype:SocketSocket的类型的类型( (SOCK_STREAMSOCK_STREAM( (流格式流格式) )、SOCK_DGRAMSOCK_DGRAM( (数据报数据报格式格式); protocolprotocol:特殊的通讯协定特殊的通讯协定( (不指定则不指定则设为设为0 0) );此函数调用此函数调用

60、成功返回成功返回SocketSocket对象对象,失败失败则则返回返回INVALID_SOCKETINVALID_SOCKET( (调用调用WSAGetLastError()WSAGetLastError()可得知原因,所有可得知原因,所有WinSocket WinSocket 的函数都可以使用这个函数来获取失败的原因的函数都可以使用这个函数来获取失败的原因) )。北京交通大学出版社北京交通大学出版社3)3)绑定端口绑定端口为监听的为监听的SocketSocket指定一个地址及端口(指定一个地址及端口(PortPort),这样客户端),这样客户端才知道待会要连接哪一个地址的哪个端口,为此需调用才知道待会要连接哪一个地址的哪个端口,为此需调用bind()bin

温馨提示

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

评论

0/150

提交评论