收藏 分享(赏)

TCP程序设计复习定稿new.doc

上传人:dreamzhangning 文档编号:2227502 上传时间:2018-09-06 格式:DOC 页数:10 大小:119.50KB
下载 相关 举报
TCP程序设计复习定稿new.doc_第1页
第1页 / 共10页
TCP程序设计复习定稿new.doc_第2页
第2页 / 共10页
TCP程序设计复习定稿new.doc_第3页
第3页 / 共10页
TCP程序设计复习定稿new.doc_第4页
第4页 / 共10页
TCP程序设计复习定稿new.doc_第5页
第5页 / 共10页
点击查看更多>>
资源描述

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

2、年间全部发完。1.2 什么是 IPv6?IPv6 是下一版本的互联网协议,也可以说是下一代互联网的协议,它的提出最初是因为随着互联网的迅速发展,IPv4 定义的有限地址空间将被耗尽,地址空间的不足必将妨碍互联网的进一步发展。为了扩大地址空间,拟通过 IPv6 重新定义地址空间。IPv6采用 128 位地址长度,几乎可以不受限制地提供地址。按保守方法估算 IPv6 实际可分配的地址,整个地球的每平方米面积上仍可分配 1000 多个地址。在 IPv6 的设计过程中除了一劳永逸地解决了地址短缺问题以外,还考虑了在 IPv4 中解决不好的其它问题,主要有端到端 IP 连接、服务质量(QoS )、安全性

3、、多播、移动性、即插即用等。1.3 IPv6 与 IPv4 相比有什么特点和优点? 1. 更大的地址空间。IPv4 中规定 IP 地址长度为 32,即有 232-1 个地址;而 IPv6 中IP 地址的长度为 128,即有 2128-1 个地址。 2. 更小的路由表。IPv6 的地址分配一开始就遵循聚类(Aggregation)的原则,这使得路由器能在路由表中用一条记录(Entry)表示一片子网,大大减小了路由器中路由表的长度,提高了路由器转发数据包的速度。 3. 增强的组播(Multicast)支持以及对流的支持(Flow-control)。这使得网络上的多媒体应用有了长足发展的机会,为服务

4、质量(QoS)控制提供了良好的网络平台. 4. 加入了对自动配置(Auto-configuration)的支持。这是对 DHCP 协议的改进和扩展,使得网络(尤其是局域网)的管理更加方便和快捷. 更高的安全性.在使用 IPv6 网络中用户可以对网络层的数据进行加密并对 IP 报文进行校验,这极大的增强了网络安全.1.4. IPv4 包头各字段含义1. Version 4 位字段,指出当前使用的 IP 版本。 2. IP Header Length (IHL) 指数据报协议头长度,具有 32 位字长。指向数据起点。正确协议头最小值为 5。 3. Type-of-Service 指出上层协议对处理

5、当前数据报所期望的服务质量,并对数据报按照重要性级别进行分配。这些 8 位字段用于分配优先级、延迟、吞吐量以及可靠性。 4. Total Length 指定整个 IP 数据包的字节长度,包括数据和协议头。其最大值为 65,535 字节。典型的主机可以接收 576 字节的数据报。 5. Identification 包含一个整数,用于识别当前数据报。该字段由发送端分配帮助接收端集中数据报分片。 6. Flags 由 3 位字段构成,其中低两位(最不重要)控制分片。低位指出数据包是否可进行分片。中间位指出在一系列分片数据包中数据包是否是最后的分片。第三位即最高位不使用。 7. Fragment O

6、ffset 13 位字段,指出与源数据报的起始端相关的分片数据位置,支持目标 IP 适当重建源数据报。 8. Time-to-Live 是一种计数器,在丢弃数据报的每个点值依次减 1 直至减少为0。这样确保数据包无止境的环路过程。 9. Protocol 指出在 IP 处理过程完成之后,有哪种上层协议接收导入数据包。 10. Header Checksum 帮助确保 IP 协议头的完整性。由于某些协议头字段的改变,如生存期(Time to Live),这就需要对每个点重新计算和检验。 Internet 协议头需要进行处理。 11. Source Address 指定发送代码。 12. Dest

7、ination Address 指定接收代码。 13. Options 允许 IP 支持各种选项,如安全性。 14. Data 包括上层信息。1.5. IPv6 包头各字段含义1. Version(版本号):4 位,IP 协议版本号,值 = 6。 2. Traffice Class(通信类别):8 位,指示 IPv6 数据流通信类别或优先级。功能类似于 IPv4 的服务类型(TOS)字段。 3. Flow Label(流标记): 20 位,IPv6 新增字段,标记需要 IPv6 路由器特殊处理的数据流。该字段用于某些对连接的服务质量有特殊要求的通信,诸如音频或视频等实时数据传输。在 IPv6

8、中,同一信源和信宿之间可以有多种不同的数据流,彼此之间以非“0”流标记区分。如果不要求路由器做特殊处理,则该字段值置为 “0”。4. Payload Length(负载长度): 16 位负载长度。负载长度包括扩展头和上层PDU,16 位最多可表示 65,535 字节负载长度。超过这一字节数的负载,该字段值置为“0”,使用扩展头逐个跳段(Hop-by-Hop)选项中的巨量负载(Jumbo Payload)选项。 5. Next Header(下一包头): 8 位,识别紧跟 IPv6 头后的包头类型,如扩展头(有的话)或某个传输层协议头(诸如 TCP,UDP 或着 ICMPv6)。 6. Hop

9、Limit(跳段数限制):8 位,类似于 IPv4 的 TTL(生命期)字段。与 IPv4 用时间来限定包的生命期不同,IPv6 用包在路由器之间的转发次数来限定包的生命期。包每经过一次转发,该字段减 1,减到 0 时就把这个包丢弃。 7. Source Address(源地址):128 位,发送方主机地址。 8. Destination Address(目的地址):128 位,在大多数情况下,目的地址即信宿地址。但如果存在路由扩展头的话,目的地址可能是发送方路由表中下一个路由器接口。TCP:定义:是一种面向连接的、可靠的、基于字节流的传送层通信协议。特点:1. 提供面向连接的服务。客户端与服

10、务器通信时,必须首先建立连接。2. 提供可靠的服务。当 TCP 向对方发送数据时,要求对方返回一个确认。如果没有接收到对方的确认,则 TCP 自动重传数据。3. TCP 对发送的数据进行排序,为每个发送字节关联一个序列号,对方根据接收到的数据序列号,对接收数据排序 ,从而保证了数据的顺序。4. TCP 提供流量控制。TCP 总是告知对方它能够接收数据的字节数。5. TCP 连接是全双工的。这意味着应用程序在任何时候,既可发送数据也可接收数据。 UDP:定义:是一种无连接的传送层协议,提供不可靠信息传输服务。特点:1. 提供无连接服务,客户端向服务器发送数据时不必先建立连接。客户端创建一个套接字

11、并向服务器发送一个数据报,然后客户端可以立即用这个套接字向另外一个服务器发送其他数据。2. 不能确保 UDP 数据报最终到达目的地。UDP 对接收的数据报不发送确认,发送端不知道数据是否被正确接收,也不会重发数据。3. UDP 传输数据较 TCP 快,占用系统资源少。Part II:Socket Programming1. Socket Address/Network byte/Socket functions1.1 IP 定址在 Windows Socket 中,SOCKADDR_IN 结构被用来指定 IP 地址和端口号,该结构声明如下:struts sockaddr_inshort sin

12、_family; /地址家族;必须为 AF_INFT 心告知程序腹胀 IP 地址家族u_shortsin_port; /服务端口号struct in_addr sin_addr; /in_add 类型的 IP 地址char sin_zero;/填充该结构的大小,使之与 SOCKADDR 结构大小相同1.2 相关函数1. WSAStartup():无论客户端还是服务器,必须首先加载 WindowsSocket 动态库(DLL)2. socket():在初始化 Windows Sockets 后,创建套接字。当该函数调用成功后,返回一个新建的套接字句柄;调用失败则返回 INVALID_SOCKET

13、。3. bind():将套接字绑定到一个已知的地址。如果函数调用成功,则返回值为 0;否则,返回值为 SOCKET_ERROR。4. listen():将套接字设置为监听模式。当该函数调用成功时,返回值为 0;否则返回 SOCKET_ERROR。5. accept():实现接受一个连接请求的功能。当该函数调用成功后,返回一个新的套接字句柄,服务器使用该套接字与客户端进行数据传输。调用失败则返回INVALID_SOCKET。6. recv():用于接收数据。调用成功时,返回值为接收的字节数;当调用失败时,返回值为 SOCKET_ERROR。7. send():用于发送数据。成功,返回实际发送的字

14、节数。失败返回SOCKET_ERROR。8. closesocket():关闭套接字,释放所占资源。9. shutdown():用于通知对方不再发送数据或者不再接收数据,或者既不发送也不接收数据。10. connect():实现连接服务器功能。成功返回 0;失败返回 SOCKET_ERROR。2. TCP/UDP I./O models (相关函数及调用次序)2.1 blocking1.1 阻塞模式套接字的优势和不足使用阻塞模式的套接字开发网络程序比较简单,容易实现。当希望能够立即发送和接收数据,且处理的套接字数量比较少的情况下,使用阻塞模式来开发网络程序比较适合。不足:在大量建立好的套接字线

15、程之间进行通信时比较困难。1.2 阻塞模式服务器和客户端工作流程1. 服务器端:WASStart()初始化动态链接库;socket()创建 socket;bind()绑定socket;listen() 监听 socket;accept() 接受新的连接;recv() 接收数据;send()发送数据;closesocket()关闭 socket;WSAcleanup()清空资源2. 客户端:WASStart()初始化动态链接库;socket()创建 socket;connect()连接服务器;send()发送数据; recv()接收数据;closesocket() 关闭socket;WSAcle

16、anup()清空资源2.2 Concurrent server based on processes/threads (linux/Windows)ioctlSocket():将套接字设置为非阻塞模式。2.1 套接字的阻塞模式与非阻塞模式原理与对比在阻塞模式下,在 I/O 操作完成前,执行的操作函数将一直等候而不会立即返回,该函数所在的线程会阻塞在这里。相反,在非阻塞模式下,套接字函数会立即返回,而不管 I/O 是否完成,该函数所在的线程会继续运行。非阻塞模式与阻塞模式相比,使用较复杂。使用非阻塞模式套接字,需要编写更多的代码。但是,非阻塞模式套接字在控制建立的多个连接,在数据的收发量不均、时

17、间不定等方面,具有优势。2.3 selectSelect():判断套接字是否存在数据,或者能否向其写入数据;返回牌就绪状态并且已经包含在 fd_set 结构中的套接字总数。调用超时则返回 0.2.3.1 接字 Select 模型原理套接字的 Select 模型,能够使 windows sockets 应用程序同时对多个套接字进行管理。调用 select()函数检查当前各个套接字的当前状态(是否存在数据,或者能否向该套接字写入数据)。并且根据该函数的返回值,判断套接字的可读可写性。然后调用相应的 API,完成数据的发送、接收等。2.3.2 Select 模型的优势和不足Select 模型优势:1

18、. 可以同时对多个建立起来的套接字进行有序的管理。2. 可以防止应用程序在一次 I/O 调用过程中,使阻塞模式套接字被迫进入阻塞状态;使非阻塞套接字产生 WSAEWOULDBLOCK 错误。3. 可以让程序开发人员把精力更多的集中在如何处理数据的发送和接收上。Select 模型的不足:完成一次 I/O 操作经历了两次 windows sockets 函数的调用,因此,其效率可能受损,导致严重的 CPU 额外负担。2.4 WSAAsyncSelectWSAAsyncSelect():请求当网络事件发生时为套接字发送消息。当调用该函数时,自动将套接字转换为非阻塞模式,2.4.1 WSAAsyncS

19、elect 模型与 select 模型的比较相同点:都可以对 windows 套接字应用程序所使用的多个套接字惊喜有效的管理。不同点:1. WSAAsyncSelect 模型是异步的;2. 发生网络时间时,应用程序得到通知的方式不同;3. WSAAsyncSelect 模型应用在基于消息的 windows 环境下,使用该模型时必须创建窗口。而 select 模型不需要创建窗口;4. 应用程序中调用 WSAAsyncSelect()函数后,自动将套接字设置为非阻塞模式。而应用程序中调用 select()函数后,并不能改变该套接字的工作方式。2.4.2 WSAAsyncSelect 模型的优势和不

20、足优势:方便了基于消息的 windows 环境下开发套接字应用程序。为确保接收所有数据提供了很好的机制。不足:它基于 windows 的消息机制,必须在应用程序中创建窗口。由于调用WSAAsyncSelect()函数后,自动将套接字设置为非阻塞状态。当应用程序为接收到网络事件调用相应的函数时,未必能够成功返回。2.5 WSAEventSelectWSACreateEvent():创建一个事件对象。WSAEventSelect():为套接字注册网络事件,使之与网络事件关联起来WSAResetEvent():将事件对象从 “已传信”状态改为 “未传信”状态WSACloseEvent():释放事件对

21、象占有的系统资源。WSAWaitForMultipleEvent():等待网络事件的发生。WSAEnumNetworkEvents():查找发生在套接字上的网络事件,并清除系统内部的网络事件记录,重围事件对象。2.5.1 WSAEventSelect 模型的优势和不足优势: 可以应用在一个非窗口的 windows sockets 程序中,实现对多个套接字的管理。不足: 每个 WSAEventSelect 模型最多只能管理 64 个套接字。2.6 Overlapper IO( Event Notification / Completion routine)CreateFile():用来创建或者打

22、开文件、管道、邮槽、通信资源、控制台、硬件设备各文件夹等几种对象。ReadFile():从指定对象上读取数据。WriteFile():将数据写入对象中。GetOverlappedResult():返回在文件、命名管道或者通信设备上执行重叠 I/O 操作的结果。2.6.1 重叠 I/O 模型原理重叠 I/O 模型是真正意义上的异步模型, windows sockets 应用程序在调用WSARecv()函数后立即返回,线程几下运行。当系统中淑准备好,并且将数据复制到用户缓冲区后,向应用程序发送通知。应用程序接到通知后,对数据进行处理。系统向应用程序发送通知的形式有两种:一是事件通知,二是完成例程。

23、2.6.2 重叠 I/O 模型与其他模型的比较Select 模型利用 select()函数主动检查系统中套接字是否满足可读条件。而WSAAsyncSelect 模型和 WSAEventSelect 模型则被动等待系统的通知。当系统发生FD_READ 网络事件时, WSAAsyncSelect 模型以消息的形式接收通知,WSAEventSelect模型以事件形式接收通知。在将数据从系统复制到用户缓冲区时,线程阻塞于函数的调用。重叠 I/O 模型与前三个模型不同。Windows sockets 应用程序在调用输入函数后,只需等待接收系统完成I/O 操作后发送通知。2.6.3 基于事件通知的重叠 I

24、/O 模型的实现步骤1. 创建具有 WSAOVERLAPPED 标志的套接字2. 为套接字定义 WSAOVERLAPPED 结构3. 调用 WSACreatEvent0 函数创建事件对象,并将该事件句柄分配该WSAOVERLAPPED 结构的 hEvent 字段4. 调用输入或者输出函数,初始化重叠 I/O 操作5. 调用 WSAWaitForMultipleEvents()函数,等待与重叠 I/O 关联在一起的事件进入“已传信”状态6. 调用 WSAWaitForMultipleEvents()函数返回后,调用 WSAResetEvent()函数,重设该事件7. 调用 WSAGetOverl

25、appedResult()函数,判断重叠 I/O 完成状态8. 对数据进行处理2.7 Completion port创建完成端口对象:CreateIoCompletionPort()函数创建服务线程:首先调用 GetSystemInfo()来获得计算机 CPU 数量,然后调用CreateThread()函数创建服务线程。套接字与完成端口关联:调用 CreateIoCompletionPort()函数来实现。发起重叠 I/O 操作:WSASend() 和 WSASendTo()函数:发送数据WSARecv() 和 WSARecvFrom():接收数据等待重叠 I/O 操作结果:调用 GetQue

26、uedCompletionStatus()来实现。取消异步操作:当关闭套接字时,调用 Cancello()函数取消等待执行的异步操作、投递完成通知包:当服务线程退出,调用 PostQueuedCompletionStatus()函数向完成端口发送一个 I/O 操作完成通知包。在服务线程中,GetQueuedCompletion 函数返回调用PostQueuedCompletionStatus()函数时传递的第 2 个,第 3 个和第 4 个参数值。完成端口模型与重叠 I/O 模型比较相同点: 都是异步模型,都可以使得套接字应用程序性能得到改善。相比之下,重叠 I/O 模型有以下不足:1. 事件

27、通知方式的不足;2. 完成例程的不足完成端口的优点:1.与事件通知方法相比,对发起重叠操作的数量不存在限制。2.与完成例程相比,该模型允许一个线程发起重叠操作,而由另外一个线程为完成的操作提供服务。3.支持 scalable 架构。3. Socket option(setsockopt/getsockopt) 套接字选项getsockopt ():获取套接字选项信息该函数声明如下:int getsockopt(SOCKET s, /套接字int level, /选项级别,有 SOL_SOCKET 和+IPPROTO_TCP 两个级别int optname, /套接字选项名称char FAR*

28、optval, /接收数据缓冲区,该参数返回套接字选项名称对应的值int FAR* optlen /缓冲区大小)如果函数调用成功,则返回值为 0.如果该函数调用失败,则返回 SOCKET_ERROR。setsockopt ():设置套接字选项该函数声明如下:int setsockopt (SOCKETs, /套接字int level, /选项级别,有 SOL_SOCKET 和+IPPROTO_TCP 两个级别int optname, /套接字选项名称char FAR* optval, /接收数据缓冲区,该参数返回套接字选项名称对应的值int FAR* optlen /缓冲区大小)如果函数调用成

29、功,则返回值为 0.如果该函数调用失败,则返回 SOCKET_ERROR。4. 使用 gethostbyname 由域名或主机名得 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_lengt

30、h;char *h_addr_list; ;解释一下这个结构:其中,char *h_name 表示的是主机的规范名。例如 的规范名其实是。char *h_aliases 表示的是主机的别名 就是 google 他自己的别名。有的时候,有的主机可能有好几个别名,这些,其实都是为了易于用户记忆而为自己的网站多取的名字。int h_addrtype 表示的是主机 ip 地址的类型,到底是 ipv4(AF_INET),还是pv6(AF_INET6)int h_length 表示的是主机 ip 地址的长度int *h_addr_lisst 表示的是主机的 ip 地址,注意,这个是以网络字节序存储的。千

31、万不要直接用 printf 带%s 参数来打这个东西,会有问题的哇。所以到真正需要打印出这个 IP 的话,需要调用 inet_ntop()。const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) :这个函数,是将类型为 af 的网络地址结构 src,转换成主机序的字符串形式,存放在长度为 cnt 的字符串中。这个函数,其实就是返回指向 dst 的一个指针。如果函数调用错误,返回值是NULL。下面是例程,有详细的注释。#include #include int main(int argc, char *ar

32、gv)char *ptr,*pptr;struct hostent *hptr;char str32;/* 取得命令后第一个参数,即要解析的域名或主机名 */ptr = argv1;/* 调用 gethostbyname()。调用结果都存在 hptr 中 */if(hptr = gethostbyname(ptr) = NULL)printf(“gethostbyname error for host:%sn“, ptr);return 0; /* 如果调用 gethostbyname 发生错误,返回 1 */* 将主机的规范名打出来 */printf(“official hostname:%

33、sn“,hptr-h_name);/* 主机可能有多个别名,将所有别名分别打出来 */for(pptr = hptr-h_aliases; *pptr != NULL; 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_

34、ntop(hptr-h_addrtype,*pptr, str, sizeof(str);break;default:printf(“unknown address typen“);break;return 0;5. Concept of raw socket 原始套接字概念原始套接字是一个特殊的套接字类型,它的创建方式跟 TCP/UDP 创建方法几乎是一摸一样,然而这种类型套接字的功能却与 TCP 或者 UDP 类型套接字的功能有很大的不同:TCP/UDP 类型的套接字只能够访问传输层以及传输层以上的数据,因为当 IP 层把数据传递给传输层时, 下层的数据包头已经被丢掉了.而原始套接字却可以

35、访问传输层以下的数据 ,所以使用 raw套接字你可以实现上至应用层的数据操作,也可以实现下至链路层的数据操作 .2.select 模型服务器端:#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)/初始化WSAData wsaData;WSAStartup(MAKEWORD(2,2), /创建 SOCKET(TCP 方式)SOCKET sockServer =

36、 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); int ret;/绑定 SOCKETret = bind(sockServer, (SOCKADDR*)/监听ret = listen(sockServer,0); SOCKET sockCl

37、ient;/定义缓冲区char bufBUF_SIZE;FD_SET readSet; /可读 SOCKET 集合FD_SET socketSet; /服务器 SOCKET 集合FD_ZERO( /清空服务器 SOCKET 列表FD_SET(sockServer, /加入监听 SOCKETwhile(true)FD_ZERO( /清空可读 SOCKET 集合readSet = socketSet;select(0, SOCKET s;for(int i=0;i WSA_MAXIMUM_WAIT_EVENTS)printf(“Too many connections“);closesocket(

38、Accept);break;NewEvent = WSACreateEvent();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 break;/ Read data from

39、 the socketrecv(SocketArrayIndex - WSA_WAIT_EVENT_0, buffer, sizeof(buffer), 0);/ Process FD_WRITE notificationif (NetworkEvents.lNetworkEvents break;send(SocketArrayIndex - WSA_WAIT_EVENT_0, buffer, sizeof(buffer), 0);if (NetworkEvents.lNetworkEvents break;closesocket(SocketArrayIndex);/ Remove soc

40、ket and associated event from/ the Socket and Event arrays and decrement/ EventTotalCompressArrays(EventArray, SocketArray, Closesocket(sockServer);WSACleanup();Completion routine(完成例程)服务器端:#include “stdafx.h“#include “unp.h“#pragma comment(lib,“ws2_32.lib“)#define DATA_BUFSIZE 4096void CALLBACK Wor

41、kerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED lpOverlapped,DWORD InFlags);DWORD WINAPI str_echo_perClient(LPVOID lpParam);typedef struct _OverlaperedPlus WSAOVERLAPPED ol;SOCKETsockfd;char dataBufDATA_BUFSIZE;WSABUF wsBuf; WSAWSAOVERLAPPEDPLUS, *LPWSAWSAOVERLAPPEDPLUS;void main(voi

42、d)/WSAWSAOVERLAPPEDPLUS OverlappedPlus;WSADATA wsaData;int clilen;struct sockaddr_in cliaddr, servaddr;SOCKET AcceptSocket, ListenSocket;/ Step 1:/ Start Winsock, and set up a listening socketWSAStartup( MAKEWORD(2,2), ListenSocket = Socket(AF_INET, SOCK_STREAM, 0);bzero(servaddr.sin_family = AF_INE

43、T;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);bind(ListenSocket, (SA *) listen(ListenSocket, LISTENQ);for (;)clilen = sizeof(cliaddr);AcceptSocket = Accept(ListenSocket, (SA *) HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)str_echo_perClient, (L

44、PVOID)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 conne

45、ctionFlags = 0;ZeroMemory(OverlappedPlus.sockfd = AcceptSocket;OverlappedPlus.wsBuf.buf = OverlappedPlus.dataBuf;OverlappedPlus.wsBuf.len = DATA_BUFSIZE;if (WSARecv(AcceptSocket, WSACleanup();return 0;while(TRUE)/ Step 5:/Index = WSAWaitForMultipleEvents(1, EventArray, FALSE, WSA_INFINITE, TRUE);Ind

46、ex = SleepEx(INFINITE, true);/ Step 6:if (Index = WAIT_IO_COMPLETION)continue;elseprintf(_T(“SleepEx() failed with error %dn“), WSAGetLastError();return 0;return 0;void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED lpOverlapped,DWORD InFlags)DWORD RecvBytes;DWORD Flags;

47、LPWSAWSAOVERLAPPEDPLUS lpOverPlus;lpOverPlus = CONTAINING_RECORD(lpOverlapped, WSAWSAOVERLAPPEDPLUS, ol);if (Error != 0 | BytesTransferred = 0)closesocket(lpOverPlus-sockfd);ExitThread(0);SOCKET AcceptSocket;AcceptSocket = lpOverPlus-sockfd;Writen(AcceptSocket, lpOverPlus-dataBuf, BytesTransferred);

48、 Flags = 0;ZeroMemory(lpOverPlus, sizeof(WSAWSAOVERLAPPEDPLUS);lpOverPlus-sockfd = AcceptSocket;lpOverPlus-wsBuf.buf = lpOverPlus-dataBuf;lpOverPlus-wsBuf.len = DATA_BUFSIZE;if (WSARecv(AcceptSocket, ExitThread(1); /设置套接字非阻塞模式unsigned long ul = 1;reVal = ioctlsocket(sServer, FIONBIO, (unsigned long*

49、)if (SOCKET_ERROR = reVal)return FALSE;Example:TCP 套接字编程实现Server.Cpp-服务器端实现int main(intargc, char* argv)WSADATA wsd; /WSADATA 变量SOCKET sServer; /服务器套接字SOCKET sClient; /客户端套接字SOCKADDR_IN addrServ; /服务器地址char bufBUF_SZIE; /接收数据缓冲区int retVal; /返回值/初始化套结字动态库if(WSAStartup(MAKEWORD(2,2), return 1;/创建套接字sServer=socket(AF_INET, SOCK_STRE

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报