




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Part I: TCP/IP协议1. IPv4和IPv6是什么?两者的特点和优点1.1 什么是IPv4?目前的全球因特网所采用的协议族是TCP/IP协议族。IP是TCP/IP协议族中网络层的协议,是TCP/IP协议族的核心协议。目前IP协议的版本号是4(简称为IPv4),发展至今已经使用了30多年。IPv4的地址位数为32位,也就是最多有2的32次方的电脑可以联到Internet上。近十年来由于互联网的蓬勃发展,IP位址的需求量愈来愈大,使得IP位址的发放愈趋严格,各项资料显示全球IPv4位址可能在2005至2008年间全部发完。1.2 什么是IPv6?IPv6是下一版本的互联网协议,也可以说
2、是下一代互联网的协议,它的提出最初是因为随着互联网的迅速发展,IPv4定义的有限地址空间将被耗尽,地址空间的不足必将妨碍互联网的进一步发展。为了扩大地址空间,拟通过IPv6重新定义地址空间。IPv6采用128位地址长度,几乎可以不受限制地提供地址。按保守方法估算IPv6实际可分配的地址,整个地球的每平方米面积上仍可分配1000多个地址。在IPv6的设计过程中除了一劳永逸地解决了地址短缺问题以外,还考虑了在IPv4中解决不好的其它问题,主要有端到端IP连接、服务质量(QoS)、安全性、多播、移动性、即插即用等。1.3 IPv6与IPv4相比有什么特点和优点? 1. 更大的地址空间。IPv4中规定
3、IP地址长度为32,即有232-1个地址;而IPv6中IP地址的长度为128,即有2128-1个地址。 2. 更小的路由表。IPv6的地址分配一开始就遵循聚类(Aggregation)的原则,这使得路由器能在路由表中用一条记录(Entry)表示一片子网,大大减小了路由器中路由表的长度,提高了路由器转发数据包的速度。 3. 增强的组播(Multicast)支持以及对流的支持(Flow-control)。这使得网络上的多媒体应用有了长足发展的机会,为服务质量(QoS)控制提供了良好的网络平台. 4. 加入了对自动配置(Auto-configuration)的支持。这是对DHCP协议的改进和扩展,使
4、得网络(尤其是局域网)的管理更加方便和快捷.更高的安全性.在使用IPv6网络中用户可以对网络层的数据进行加密并对IP报文进行校验,这极大的增强了网络安全.1.4. IPv4包头各字段含义1. Version 4位字段,指出当前使用的 IP 版本。2. IP Header Length (IHL) 指数据报协议头长度,具有32位字长。指向数据起点。正确协议头最小值为5。3. Type-of-Service 指出上层协议对处理当前数据报所期望的服务质量,并对数据报按照重要性级别进行分配。这些8位字段用于分配优先级、延迟、吞吐量以及可靠性。4. Total Length 指定整个 IP 数据包的字节
5、长度,包括数据和协议头。其最大值为65,535字节。典型的主机可以接收576字节的数据报。5. Identification 包含一个整数,用于识别当前数据报。该字段由发送端分配帮助接收端集中数据报分片。6. Flags 由3位字段构成,其中低两位(最不重要)控制分片。低位指出数据包是否可进行分片。中间位指出在一系列分片数据包中数据包是否是最后的分片。第三位即最高位不使用。7. Fragment Offset 13位字段,指出与源数据报的起始端相关的分片数据位置,支持目标IP适当重建源数据报。8. Time-to-Live 是一种计数器,在丢弃数据报的每个点值依次减1直至减少为0。这样确保数据
6、包无止境的环路过程。9. Protocol 指出在 IP 处理过程完成之后,有哪种上层协议接收导入数据包。10. Header Checksum 帮助确保 IP 协议头的完整性。由于某些协议头字段的改变,如生存期(Time to Live),这就需要对每个点重新计算和检验。Internet 协议头需要进行处理。11. Source Address 指定发送代码。12. Destination Address 指定接收代码。13. Options 允许 IP 支持各种选项,如安全性。14. Data 包括上层信息。1.5. IPv6包头各字段含义1. Version(版本号):4位,IP协议版本
7、号,值= 6。 2. Traffice Class(通信类别):8位,指示IPv6数据流通信类别或优先级。功能类似于IPv4的服务类型(TOS)字段。 3. Flow Label(流标记):20位,IPv6新增字段,标记需要IPv6路由器特殊处理的数据流。该字段用于某些对连接的服务质量有特殊要求的通信,诸如音频或视频等实时数据传输。在IPv6中,同一信源和信宿之间可以有多种不同的数据流,彼此之间以非“0”流标记区分。如果不要求路由器做特殊处理,则该字段值置为“0”。 4. Payload Length(负载长度):16位负载长度。负载长度包括扩展头和上层PDU,16位最多可表示65,535字节
8、负载长度。超过这一字节数的负载,该字段值置为“0”,使用扩展头逐个跳段(Hop-by-Hop)选项中的巨量负载(Jumbo Payload)选项。 5. Next Header(下一包头):8位,识别紧跟IPv6头后的包头类型,如扩展头(有的话)或某个传输层协议头(诸如TCP,UDP或着ICMPv6)。6. Hop Limit(跳段数限制):8位,类似于IPv4的TTL(生命期)字段。与IPv4用时间来限定包的生命期不同,IPv6用包在路由器之间的转发次数来限定包的生命期。包每经过一次转发,该字段减1,减到0时就把这个包丢弃。 7. Source Address(源地址):128位,发送方主机
9、地址。 8. Destination Address(目的地址):128位,在大多数情况下,目的地址即信宿地址。但如果存在路由扩展头的话,目的地址可能是发送方路由表中下一个路由器接口。TCP:定义:是一种面向连接的、可靠的、基于字节流的传送层通信协议。 特点:1. 提供面向连接的服务。客户端与服务器通信时,必须首先建立连接。2. 提供可靠的服务。当TCP向对方发送数据时,要求对方返回一个确认。如果没有接收到对方的确认,则TCP自动重传数据。3. TCP 对发送的数据进行排序,为每个发送字节关联一个序列号,对方根据接收到的数据序列号,对接收数据排序 ,从而保证了数据的顺序。4. TCP提供流量控
10、制。TCP总是告知对方它能够接收数据的字节数。5. TCP连接是全双工的。这意味着应用程序在任何时候,既可发送数据也可接收数据。 UDP:定义:是一种无连接的传送层协议,提供不可靠信息传输服务。 特点:1. 提供无连接服务,客户端向服务器发送数据时不必先建立连接。客户端创建一个套接字并向服务器发送一个数据报,然后客户端可以立即用这个套接字向另外一个服务器发送其他数据。2. 不能确保UDP数据报最终到达目的地。UDP对接收的数据报不发送确认,发送端不知道数据是否被正确接收,也不会重发数据。3. UDP传输数据较TCP快,占用系统资源少。Part II:Socket Programming1. S
11、ocket Address/Network byte/Socket functions1.1 IP定址在Windows Socket中,SOCKADDR_IN结构被用来指定IP地址和端口号,该结构声明如下:struts sockaddr_inshortsin_family;/地址家族;必须为AF_INFT心告知程序腹胀IP地址家族u_shortsin_port;/服务端口号structin_addr sin_addr;/in_add类型的IP地址charsin_zero;/填充该结构的大小,使之与SOCKADDR结构大小相同1.2 相关函数1. WSAStartup():无论客户端还是服务器,
12、必须首先加载WindowsSocket动态库(DLL)2. socket():在初始化Windows Sockets后,创建套接字。当该函数调用成功后,返回一个新建的套接字句柄;调用失败则返回INVALID_SOCKET。3. bind():将套接字绑定到一个已知的地址。如果函数调用成功,则返回值为0;否则,返回值为SOCKET_ERROR。4. listen():将套接字设置为监听模式。当该函数调用成功时,返回值为0;否则返回SOCKET_ERROR。5. accept():实现接受一个连接请求的功能。当该函数调用成功后,返回一个新的套接字句柄,服务器使用该套接字与客户端进行数据传输。调用失
13、败则返回INVALID_SOCKET。6. recv():用于接收数据。调用成功时,返回值为接收的字节数;当调用失败时,返回值为SOCKET_ERROR。7. send():用于发送数据。成功,返回实际发送的字节数。失败返回SOCKET_ERROR。8. closesocket():关闭套接字,释放所占资源。9. shutdown():用于通知对方不再发送数据或者不再接收数据,或者既不发送也不接收数据。10. connect():实现连接服务器功能。成功返回0;失败返回SOCKET_ERROR。2. TCP/UDP I./O models (相关函数及调用次序)2.1 blocking1.1
14、阻塞模式套接字的优势和不足使用阻塞模式的套接字开发网络程序比较简单,容易实现。当希望能够立即发送和接收数据,且处理的套接字数量比较少的情况下,使用阻塞模式来开发网络程序比较适合。不足:在大量建立好的套接字线程之间进行通信时比较困难。1.2 阻塞模式服务器和客户端工作流程1. 服务器端:WASStart()初始化动态链接库;socket()创建socket;bind()绑定socket;listen()监听socket;accept()接受新的连接;recv()接收数据;send()发送数据;closesocket()关闭socket;WSAcleanup()清空资源2. 客户端:WASStar
15、t()初始化动态链接库;socket()创建socket;connect()连接服务器;send()发送数据;recv()接收数据;closesocket()关闭socket;WSAcleanup()清空资源2.2 Concurrent server based on processes/threads (linux/Windows)ioctlSocket():将套接字设置为非阻塞模式。2.1 套接字的阻塞模式与非阻塞模式原理与对比 在阻塞模式下,在I/O操作完成前,执行的操作函数将一直等候而不会立即返回,该函数所在的线程会阻塞在这里。相反,在非阻塞模式下,套接字函数会立即返回,而不管I/O是
16、否完成,该函数所在的线程会继续运行。非阻塞模式与阻塞模式相比,使用较复杂。使用非阻塞模式套接字,需要编写更多的代码。但是,非阻塞模式套接字在控制建立的多个连接,在数据的收发量不均、时间不定等方面,具有优势。2.3 selectSelect():判断套接字是否存在数据,或者能否向其写入数据;返回牌就绪状态并且已经包含在fd_set结构中的套接字总数。调用超时则返回0.2.3.1 接字Select模型原理套接字的Select模型,能够使windows sockets 应用程序同时对多个套接字进行管理。调用select()函数检查当前各个套接字的当前状态(是否存在数据,或者能否向该套接字写入数据)。
17、并且根据该函数的返回值,判断套接字的可读可写性。然后调用相应的API,完成数据的发送、接收等。2.3.2 Select模型的优势和不足Select模型优势:1. 可以同时对多个建立起来的套接字进行有序的管理。2. 可以防止应用程序在一次I/O调用过程中,使阻塞模式套接字被迫进入阻塞状态;使非阻塞套接字产生WSAEWOULDBLOCK错误。3. 可以让程序开发人员把精力更多的集中在如何处理数据的发送和接收上。Select模型的不足:完成一次I/O操作经历了两次windows sockets函数的调用,因此,其效率可能受损,导致严重的CPU额外负担。2.4 WSAAsyncSelectWSAAsy
18、ncSelect():请求当网络事件发生时为套接字发送消息。当调用该函数时,自动将套接字转换为非阻塞模式,2.4.1 WSAAsyncSelect模型与select模型的比较相同点:都可以对windows套接字应用程序所使用的多个套接字惊喜有效的管理。不同点:1. WSAAsyncSelect模型是异步的;2. 发生网络时间时,应用程序得到通知的方式不同;3. WSAAsyncSelect模型应用在基于消息的windows环境下,使用该模型时必须创建窗口。而select模型不需要创建窗口;4. 应用程序中调用WSAAsyncSelect()函数后,自动将套接字设置为非阻塞模式。而应用程序中调用
19、select()函数后,并不能改变该套接字的工作方式。2.4.2 WSAAsyncSelect模型的优势和不足优势:方便了基于消息的windows环境下开发套接字应用程序。为确保接收所有数据提供了很好的机制。不足:它基于windows的消息机制,必须在应用程序中创建窗口。由于调用WSAAsyncSelect()函数后,自动将套接字设置为非阻塞状态。当应用程序为接收到网络事件调用相应的函数时,未必能够成功返回。2.5 WSAEventSelectWSACreateEvent():创建一个事件对象。WSAEventSelect():为套接字注册网络事件,使之与网络事件关联起来WSAResetEve
20、nt():将事件对象从“已传信”状态改为“未传信”状态WSACloseEvent():释放事件对象占有的系统资源。WSAWaitForMultipleEvent():等待网络事件的发生。WSAEnumNetworkEvents():查找发生在套接字上的网络事件,并清除系统内部的网络事件记录,重围事件对象。2.5.1 WSAEventSelect模型的优势和不足优势:可以应用在一个非窗口的windows sockets 程序中,实现对多个套接字的管理。不足: 每个WSAEventSelect 模型最多只能管理64个套接字。2.6 Overlapper IO( Event Notification
21、 / Completion routine)CreateFile():用来创建或者打开文件、管道、邮槽、通信资源、控制台、硬件设备各文件夹等几种对象。ReadFile():从指定对象上读取数据。WriteFile():将数据写入对象中。GetOverlappedResult():返回在文件、命名管道或者通信设备上执行重叠I/O操作的结果。2.6.1 重叠I/O模型原理重叠I/O模型是真正意义上的异步模型,windows sockets 应用程序在调用WSARecv()函数后立即返回,线程几下运行。当系统中淑准备好,并且将数据复制到用户缓冲区后,向应用程序发送通知。应用程序接到通知后,对数据进行
22、处理。系统向应用程序发送通知的形式有两种:一是事件通知,二是完成例程。2.6.2 重叠I/O模型与其他模型的比较Select 模型利用select()函数主动检查系统中套接字是否满足可读条件。而WSAAsyncSelect模型和WSAEventSelect模型则被动等待系统的通知。当系统发生FD_READ网络事件时,WSAAsyncSelect模型以消息的形式接收通知,WSAEventSelect模型以事件形式接收通知。在将数据从系统复制到用户缓冲区时,线程阻塞于函数的调用。重叠I/O模型与前三个模型不同。Windows sockets 应用程序在调用输入函数后,只需等待接收系统完成I/O操作
23、后发送通知。2.6.3 基于事件通知的重叠I/O模型的实现步骤1. 创建具有WSAOVERLAPPED标志的套接字2. 为套接字定义WSAOVERLAPPED结构3. 调用WSACreatEvent0函数创建事件对象,并将该事件句柄分配该WSAOVERLAPPED结构的hEvent字段4. 调用输入或者输出函数,初始化重叠I/O操作5. 调用WSAWaitForMultipleEvents()函数,等待与重叠I/O关联在一起的事件进入“已传信”状态6. 调用WSAWaitForMultipleEvents()函数返回后,调用WSAResetEvent()函数,重设该事件7. 调用WSAGetO
24、verlappedResult()函数,判断重叠I/O完成状态8. 对数据进行处理2.7 Completion port创建完成端口对象:CreateIoCompletionPort()函数创建服务线程:首先调用GetSystemInfo()来获得计算机CPU数量,然后调用CreateThread()函数创建服务线程。套接字与完成端口关联:调用CreateIoCompletionPort()函数来实现。发起重叠I/O操作:WSASend() 和WSASendTo()函数:发送数据WSARecv() 和WSARecvFrom():接收数据等待重叠I/O操作结果:调用GetQueuedComple
25、tionStatus()来实现。取消异步操作:当关闭套接字时,调用Cancello()函数取消等待执行的异步操作、投递完成通知包:当服务线程退出,调用PostQueuedCompletionStatus()函数向完成端口发送一个I/O操作完成通知包。在服务线程中,GetQueuedCompletion函数返回调用PostQueuedCompletionStatus()函数时传递的第2个,第3个和第4个参数值。完成端口模型与重叠I/O模型比较相同点:都是异步模型,都可以使得套接字应用程序性能得到改善。相比之下,重叠I/O模型有以下不足:1.事件通知方式的不足;2.完成例程的不足完成端口的优点:1
26、.与事件通知方法相比,对发起重叠操作的数量不存在限制。2.与完成例程相比,该模型允许一个线程发起重叠操作,而由另外一个线程为完成的操作提供服务。3.支持scalable架构。3. Socket option(setsockopt/getsockopt) 套接字选项getsockopt ():获取套接字选项信息该函数声明如下:int getsockopt(SOCKETs,/套接字int level, /选项级别,有SOL_SOCKET和+IPPROTO_TCP两个级别intoptname,/套接字选项名称charFAR*optval,/接收数据缓冲区,该参数返回套接字选项名称对应的值int FA
27、R*optlen/缓冲区大小)如果函数调用成功,则返回值为0.如果该函数调用失败,则返回SOCKET_ERROR。setsockopt ():设置套接字选项该函数声明如下:int setsockopt (SOCKETs,/套接字int level, /选项级别,有SOL_SOCKET和+IPPROTO_TCP两个级别intoptname,/套接字选项名称charFAR*optval,/接收数据缓冲区,该参数返回套接字选项名称对应的值int FAR*optlen/缓冲区大小)如果函数调用成功,则返回值为0.如果该函数调用失败,则返回SOCKET_ERROR。4. 使用gethostbyname由
28、域名或主机名得IP地址 使用这个东西,首先要包含2个头文件:#include #include struct hostent *gethostbyname(const char *name);这个函数的传入值是域名或者主机名,例如,wpc等等。传出值,是一个hostent的结构(如下)。如果函数调用失败,将返回NULL。struct hostent char *h_name; char *h_aliases; int h_addrtype; int h_length; char *h_addr_list; ;解释一下这个结构:其中, char *h_name 表示的是主机的规范名。例如的规范名
29、其实是。 char*h_aliases 表示的是主机的别名就是google他自己的别名。有的时候,有的主机可能有好几个别名,这些,其实都是为了易于用户记忆而为自己的网站多取的名字。 int h_addrtype 表示的是主机ip地址的类型,到底是ipv4(AF_INET),还是pv6(AF_INET6)int h_length 表示的是主机ip地址的长度 int *h_addr_lisst 表示的是主机的ip地址,注意,这个是以网络字节序存储的。千万不要直接用printf带%s参数来打这个东西,会有问题的哇。所以到真正需要打印出这个IP的话,需要调用inet_ntop()。 const cha
30、r *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) : 这个函数,是将类型为af的网络地址结构src,转换成主机序的字符串形式,存放在长度为cnt的字符串中。 这个函数,其实就是返回指向dst的一个指针。如果函数调用错误,返回值是NULL。下面是例程,有详细的注释。#include #include int main(int argc, char *argv) char *ptr,*pptr; struct hostent *hptr; char str32; /* 取得命令后第一个参数,即要解析的域名或主机名 */
31、ptr = argv1; /* 调用gethostbyname()。调用结果都存在hptr中 */ if(hptr = gethostbyname(ptr) = NULL) printf(gethostbyname error for host:%sn, ptr); return 0; /* 如果调用gethostbyname发生错误,返回1 */ /* 将主机的规范名打出来 */ printf(official hostname:%sn,hptr-h_name); /* 主机可能有多个别名,将所有别名分别打出来 */ for(pptr = hptr-h_aliases; *pptr != N
32、ULL; pptr+) printf( alias:%sn,*pptr); /* 根据地址类型,将地址打出来 */ switch(hptr-h_addrtype) case AF_INET: case AF_INET6: pptr=hptr-h_addr_list; /* 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数 */ for(;*pptr!=NULL;pptr+) printf( address:%sn, inet_ntop(hptr-h_addrtype,*pptr, str, sizeof(str); break; default: printf(unknown
33、 address typen); break; return 0;5. Concept of raw socket原始套接字概念原始套接字是一个特殊的套接字类型,它的创建方式跟TCP/UDP创建方法几乎是一摸一样,然而这种类型套接字的功能却与TCP或者UDP类型套接字的功能有很大的不同:TCP/UDP类型的套接字只能够访问传输层以及传输层以上的数据,因为当IP层把数据传递给传输层时,下层的数据包头已经被丢掉了.而原始套接字却可以访问传输层以下的数据,所以使用raw套接字你可以实现上至应用层的数据操作,也可以实现下至链路层的数据操作.2.select模型服务器端:#include stdafx.
34、h#include winsock2.h#pragma comment(lib, ws2_32.lib)#define BUF_SIZE 128#define PORT_NUM 5555int main(int argc, char* argv)/初始化WSAData wsaData;WSAStartup(MAKEWORD(2,2), &wsaData);/创建SOCKET(TCP方式)SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);/填充SOCKET ADDRESSSOCKADDR_IN sAddr; sAddr.sin_family
35、= AF_INET; sAddr.sin_port = htons(PORT_NUM);sAddr.sin_addr.s_addr = htonl(INADDR_ANY); int nAddrLen = sizeof(sAddr); int ret;/绑定SOCKETret = bind(sockServer, (SOCKADDR*)&sAddr, nAddrLen);/监听ret = listen(sockServer,0); SOCKET sockClient;/定义缓冲区char bufBUF_SIZE;FD_SET readSet;/可读SOCKET集合FD_SET socketSet
36、;/服务器SOCKET集合FD_ZERO(&socketSet);/清空服务器SOCKET列表FD_SET(sockServer, &socketSet);/加入监听SOCKETwhile(true)FD_ZERO(&readSet); /清空可读SOCKET集合readSet = socketSet;select(0, &readSet, NULL, NULL, NULL);SOCKET s;for(int i=0;isocketSet.fd_count;i+)s = socketSet.fd_arrayi; if(FD_ISSET(s, &readSet) if(s = sockServe
37、r) sockClient=accept(sockServer, NULL, NULL);FD_SET(sockClient, &socketSet); else /清空缓冲区memset(buf,0, BUF_SIZE);/接收客户端数据 ret = recv(sockClient, buf, BUF_SIZE, 0);if(ret = 0) continue;/把接收到客户端的数据回传给客端ret = send(sockClient, buf, ret, 0);if(ret = 0) continue;/关闭SOCKET closesocket(sockServer);/清空资源WSACl
38、eanup();return 0;4. WSAEventSelect模型服务器端:#include stdafx.h#include winsock2.h#pragma comment(lib, ws2_32.lib)#define BUF_SIZE 128#define PORT_NUM 5555int main(int argc, char* argv)SOCKET SocketArrayWSA_MAXIMUM_WAIT_EVENTS;WSAEVENT EventArrayWSA_MAXIMUM_WAIT_EVENTS,NewEvent;DWORD EventTotal = 0;DWORD
39、 Index, i;/初始化WSAData wsaData;WSAStartup(MAKEWORD(2,2), &wsaData);/创建SOCKET(TCP方式)SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);/填充SOCKET ADDRESSSOCKADDR_IN sAddr;sAddr.sin_family = AF_INET;sAddr.sin_port = htons(PORT_NUM);sAddr.sin_addr.s_addr = htonl(INADDR_ANY);int nAddrLen = sizeof(sAddr);
40、int ret;/绑定SOCKETret = bind(sockServer, (SOCKADDR*)&sAddr, nAddrLen);NewEvent = WSACreateEvent();WSAEventSelect(Listen, NewEvent,FD_ACCEPT|FD_CLOSE);/监听ret = listen(sockServer,0);SocketArrayEventTotal = Listen;EventArrayEventTotal = NewEvent;EventTotal+;while(true) / Wait for network events on all s
41、ocketsIndex=WSAWaitForMultipleEvents(EventTotal,EventArray, FALSE, WSA_INFINITE, FALSE);Index = Index - WSA_WAIT_EVENT_0;/ Iterate through all events to see if more than one is signaled for(i=Index; i WSA_MAXIMUM_WAIT_EVENTS)printf(Too many connections);closesocket(Accept);break;NewEvent = WSACreate
42、Event();WSAEventSelect(Accept, NewEvent,FD_READ|FD_WRITE|FD_CLOSE);EventArrayEventTotal = NewEvent;SocketArrayEventTotal = Accept;EventTotal+;printf(Socket %d connectedn, Accept); / Process FD_READ notificationif (NetworkEvents.lNetworkEvents & FD_READ)if (NetworkEvents.iErrorCodeFD_READ_BIT != 0)pr
43、intf(FD_READ failed with error %dn, NetworkEvents.iErrorCodeFD_READ_BIT);break;/ Read data from the socketrecv(SocketArrayIndex - WSA_WAIT_EVENT_0, buffer, sizeof(buffer), 0);/ Process FD_WRITE notificationif (NetworkEvents.lNetworkEvents & FD_WRITE)if (NetworkEvents.iErrorCodeFD_WRITE_BIT != 0)prin
44、tf(FD_WRITE failed with error %dn, NetworkEvents.iErrorCodeFD_WRITE_BIT);break;send(SocketArrayIndex - WSA_WAIT_EVENT_0, buffer, sizeof(buffer), 0);if (NetworkEvents.lNetworkEvents & FD_CLOSE)if (NetworkEvents.iErrorCodeFD_CLOSE_BIT != 0)printf(FD_CLOSE failed with error %dn, NetworkEvents.iErrorCod
45、eFD_CLOSE_BIT);break;closesocket(SocketArrayIndex);/ Remove socket and associated event from/ the Socket and Event arrays and decrement/ EventTotalCompressArrays(EventArray, SocketArray, &EventTotal);Closesocket(sockServer);WSACleanup();Completion routine(完成例程)服务器端:#include stdafx.h#include .unp.h#p
46、ragma comment(lib,ws2_32.lib)#define DATA_BUFSIZE 4096void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED lpOverlapped,DWORD InFlags);DWORD WINAPI str_echo_perClient(LPVOID lpParam);typedef struct _OverlaperedPlus WSAOVERLAPPED ol;SOCKETsockfd;char dataBufDATA_BUFSIZE;WS
47、ABUF wsBuf; WSAWSAOVERLAPPEDPLUS, *LPWSAWSAOVERLAPPEDPLUS;void main(void) /WSAWSAOVERLAPPEDPLUS OverlappedPlus;WSADATAwsaData;int clilen; struct sockaddr_incliaddr, servaddr;SOCKET AcceptSocket, ListenSocket; / Step 1: / Start Winsock, and set up a listening socket WSAStartup( MAKEWORD(2,2), &wsaDat
48、a );ListenSocket = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr);servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);bind(ListenSocket, (SA *) &servaddr, sizeof(servaddr);listen(ListenSocket, LISTENQ);for (;)clilen = siz
49、eof(cliaddr);AcceptSocket = Accept(ListenSocket, (SA *) &cliaddr, &clilen);HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)str_echo_perClient, (LPVOID)AcceptSocket, 0, NULL);CloseHandle(hThread); WSACleanup();DWORD WINAPI str_echo_perClient(LPVOID lpParam)WSAWSAOVERLAPPEDPLUS OverlappedPlus; SOCKET AcceptSocket = (SOCKET)lpParam;/WSABUF DataBuf;/WSAEVENT EventArrayMAXIMUM_WAIT_OBJECTS;DWORD Flags, RecvBytes, Index;/ Step 2: / Accept a new connection Flags = 0; ZeroMemory(&OverlappedPlus, sizeof(WSAWSAOVERLAPPEDPLUS);OverlappedPlus.sock
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 邯郸防爆墙施工方案
- DB3709T 038-2025 泰山茶 山地低产茶园提升改造技术规程
- 充电施工方案
- 钢管脚手架搭拆施工方案
- 寿光市圣发育苗厂生态养殖科普基地项目生态影响类报告表
- 北京密云二模数学试卷
- 山东省五莲县马咤寺村2号矿区饰面花岗岩矿采矿权出让收益评估报告及附表
- 地铁风管安装工程施工方案
- 日海智能:拟质押日海智能设备(珠海)有限公司股权涉及其股东全部权益价值资产评估报告
- 张口式帘式防护网施工方案
- 2025年高考数学复习大题题型归纳:解三角形(原卷)
- 高中语文(统编版)选必下册全册单元教材解读课件
- 医院软式内镜清洗消毒技术规范
- 2024年中央空调市场占有率分析:中央空调国产品牌市场占有率上升至52.57%
- 2024年电力交易员(中级工)职业鉴定理论考试题库-下(多选、判断题)
- 2024年江苏广播电视局事业单位笔试真题
- 轮胎英语词汇
- 按摩技师签订劳动合同注意事项
- 项目保证金协议书范本
- 2022-8口腔质控督查表(培训用)
- TD/T 1054-2018 土地整治术语(正式版)
评论
0/150
提交评论