对于TCP协议中IOCP模型的一些简单的理解

请不要觉得这一篇没有代码的文章没意义,对IOCP模型的代码,百度搜索可以得到很多,但是后续很多需要纠结的地方,很多人都经历过,如果你已经在尝试写IOCP服务端了,那么你很可能会对写代码之外的一些设计问题很纠结,那么本文很可能是对你有所帮助的,这一个帖子是我开的讨论帖,我不是很懂CSDN的帖子分数的意义,我觉得那对于我这种1年难得发1贴的人来说估计也没什么作用,但我很希望大家能一起参与进来讨论:http://bbs.csdn.net/topics/390890567?page=1#post-398223652

首先一点,我要说的是,我个人认为,在IOCP TCP服务端,IO重叠的意义不大,为什么这么说呢?

TCP是一个数据包流,TCP并不会向使用者保证所谓的一条封包的完整性,同样的,TCP也没有限定使用必须每一次发送只能是一条完整的封包,那么实际上在TCP 服务器中,如果使用者真正的考虑到这一点,就应该尽可能的将数条客户端的请求结果在一段固定分配的缓冲区上构建出来,然后通过WSASend一次性投递给操作系统。

那么,说到WSASend,就应该好好考虑WSABUF参数的问题了,百度百科中提到 lpBuffers 是可以是局部变量,因为操作系统会在调用返回前对参数数组做一份拷贝,这里指的仅仅是WSABUF数组,并不是这个结构中的东西操作系统也会保存,msdn中对WSABUF.buf 的解释如下:

once the WSASend function is called, the system owns these buffers and the application may not access them

当 WSASend 被调用时,操作系统拥有这些缓冲区,应用程序不能访问它们,注意它的用词是may not,我的理解是,应用程序其实是可以访问的,但是如果是在发送完成前操作了这个缓冲区的数据,那么,发送出去的结果,就有问题了,这个问题先不谈了。

那么从这里可以看出,在IOCP中,在完成端口通知完成之前,使用者是有责任保证WSABUF.buf是必须有效的指针,可这和IO重叠有什么关系呢?举个简单的例子说下:

服务端投递了WSARecv,完成端口通知完成时,收到了一大串东西,假如,这一串东西里含有100条客户端的请求,每一条请求,都需要服务端一 一应答。

如果是这种情况,虽然有很多文章提到过,连续的使用WSASend是没有问题的,多次调用,那么必然要涉及到一个问题,缓冲区必须要是动态分配的,发完了又清理掉,或者你有能力实现高效的内存池,但是不管是如何实现,IOCP这种基于线程池的技术,都必要要涉及到互斥,不管你设计的东西有多么高效,但是在这一步骤上,线程池已经没有任何意义了,就算你从new malloc VirtualAlloc等等分配内存的东西,操作系统也是要经过互斥,速度比自己的内存池还要慢,那么从这里来看,任何影响到线程池效率的方式,在这里,都是和IOCP模型的基本思想背道而驰的,因为我们的目的是要利用IOCP处理更多的连接,处理更多的请求,如果我们把主要的精力放到如何释放内存,如何管理内存池,那么,这和我们最初的目的,不是就完全不相同了么?

我要说的是,请不要忽视TCP 流的思想,既然是TCP,我们何必去一条一条的发送呢?在TCP中,实现一套完整的协议头来正确的处理,是一种必须做的事了,否则还用TCP干什么?那么,对于大家所谓的粘包,半包这种问题,都已经处理得很熟练了,实际上,也就是在协议头中有长度信息嘛,那么为什么不考虑,将数条包直接在一段缓冲区中直接构建出来呢?客户端发送给我们的东西,既然是会粘在一起的,那么,我们发送给客户端的东西,实际上也可能是粘在一起的,既然可能粘在一起,已经是一种必然,我们为什么不索性让它们直接粘在一起呢?

说到这里,没有这么做的大部分人已经都知道应该怎么做了,但此时,新的问题来了,既然决定要在一段缓冲区上直接构建应答包了,那么我们如何保证这个缓冲区的大小是否够用,我们不希望随时new delete malloc mfree等,如果不动态分配,不使用后备缓冲区的技术,我们无法保证缓冲区是否够用。

思前想后,想了无数种办法,要保证缓冲区绝对够用,就没可能不动态分配,那么,干脆就不要保证缓冲区是否够,而且对于较长的应答包,我们也无法完全保证缓冲区是否够。

步骤如下:

1、投递WSARecv

2、假如收到客户端100条请求粘在一起

3、进行协议解密,分包流程,一条一条的进行,同时将应答结果直接填到发送缓冲区里,这个过程不使用任何动态分配,如果缓冲区不够了,保存好处理到什么位置。然后将已经处理好的部分WSASend投递出去。

4、完成端口通知完成WSASend后,再来看,上次请求有没有处理完,如果没有,继续循环3,4步骤。

5、直到上次接收到的请求处理完成时,如果最后余下的字节为不完整的请求,使用memmove将数据往接收缓冲区头部移动,下次投递的buf为,首地址 + 剩余的长度,len为固定分配的长度 - 剩余的长度,执行步骤1.



时间: 2024-07-30 21:52:49

对于TCP协议中IOCP模型的一些简单的理解的相关文章

(1)网络编程的常识 (2)基于tcp协议的编程模型 (3)tcp协议和udp协议的比较 (4)基于udp协议的编程模型

1.网络编程的常识 目前主流的网络通讯软件有:微信.QQ.YY.陌陌.探探.飞信.阿里旺旺.... 在吗? 1.1 七层网络模型(熟悉) 为了保证数据传递的可靠安全等等,ISO(国际标准委员会组织)将数据的传递从逻辑上划分为以下七层: 应用层.表示层.会话层.传输层.网络层.数据链路层.物理层. 在发送数据之前要按照上述七层协议从上到下一层一层进行加包处理,再发送出去; 在接收数据之后要按照上述七层协议从下到上一层一层进行拆包处理,再解析出来: 1.2 常用的协议(熟悉) http协议 - 超文

TCP协议中的三次握手和四次挥手(图解)【转】

建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. [更新于2017.01.04 ]该部分内容配图有误,请大家见谅,正确的配图如下,错误配图也不删了,大家可以比较下,对比理解效果更好.这么久才来更新,抱歉!! 错误配图如下: 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源.Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了. 那如何断开连接呢?

TCP 协议中的 Window Size与吞吐量

原地址:http://blog.sina.com.cn/s/blog_c5c2d6690102wpxl.html TCP协议中影响实际业务流量的参数很多,这里主要分析一下窗口的影响. ?TCP窗口目的 为了获得最优的连接速率,使用TCP窗口来控制流速率(flow control),滑动窗口就是一种主要的机制.这个窗口允许源端在给定连接传送数据分段而不用等待目标端返回ACK,一句话描述:窗口的大小决定在不需要对端响应(acknowledgement)情况下传送数据的数量.?官方定义:"The am

TCP协议中的计时器

说明:  本文仅供学习交流,转载请标明出处,欢迎转载! 本文是以下文献相关内容的总结 [1] <TCP/IP详解 卷1:协议> [2] <TCP/IP协议族 第4版> [3] <计算机网络 第5版> TCP协议通常包括4种计时器:重传计时器.持续计时器.保活计时器和时间等待计时器. 重传计时器:Retransmission Timer,该计时器用于整个连接期间,用于处理RTO(重传超时).当一个报文从发送队列发出去后,就启动该计时器.若在RTO之内收到了该报文的ACK,

TCP协议中的SO_LINGER选项

TCP协议中的SO_LINGER选项 SO_LINGER选项用来设置延迟关闭的时间,等待套接字发送缓冲区中的数据发送完成.没有设置该选项时,在调用close()后,在发送完FIN后会立即进行一些清理工作并返回.如果设置了SO_LINGER选项,并且等待时间为正值,则在清理之前会等待一段时间. 以调用close()主动关闭为例,在发送完FIN包后,会进入FIN_WAIT_1状态.如果没有延迟关闭(即设置SO_LINGER选项),在调用tcp_send_fin()发送FIN后会立即调用sock_or

TCP协议中RTO的计算

说明:  本文仅供学习交流,转载请标明出处,欢迎转载! 本文是以下文献相关内容的总结 [1] <TCP/IP详解 卷1:协议> [2] <TCP/IP协议族 第4版> [3] <计算机网络 第5版> TCP协议中经常会发生超时重传的情况,我们知道超时重传中的"时"是即RTO.RTO是Retransmission Time-OutD的缩写,该时间决定了发送方在发送数据后,在多长时间内如果没有收到ACK,就重置重传计时器,并重传上次发送失败的报文.那么R

TCP协议中的标志位

TCP/IP协议通常放在一起来说,但是它们是两个不同的协议,所起的作用也不一样. IP协议是用来查找地址的,对应于网际互联层. TCP协议是用来规范传输规则的,对应着传输层. IP协议只负责找到地址,具体传输的工作交给TCP来完成. TCP在传输之前会进行三次沟通,一般称为“三握手”:传输数据断开的时候需要进行四次沟通,一般称为“四挥手”. 要理解这个过程首先需要理解TCP中的两个序号和三个标志位的含义: seq:sequence number的缩写,表示所传数据的序号.TCP传输时每一个字节都

TCP 协议中MSS的理解

在介绍MSS之前我们必须要理解下面的几个重要的概念.MTU: Maxitum Transmission Unit 最大传输单元MSS: Maxitum Segment Size 最大分段大小PPPoE: PPP Over Ethernet(在以太网上承载PPP协议),就是因为这个协议的出现我们才有必要修改我们的MSS或者是MTU值.MTU最大传输单元,这个最大传输单元实际上和链路层协议有着密切的关系,EthernetII帧的结构DMAC+SMAC+Type+Data+CRC          

tcp协议中mss的理解

在介绍MSS之前我们必须要理解下面的几个重要的概念.<blockquote>MTU: Maxitum Transmission Unit 最大传输单元MSS: Maxitum Segment Size 最大分段大小PPPoE: PPP Over Ethernet(在以太网上承载PPP协议),就是因为这个协议的出现我们才有必要修改我们的MSS或者是MTU值.</blockquote>MTU最大传输单元,这个最大传输单元实际上和链路层协议有着密切的关系,EthernetII帧的结构&l