找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4587|回复: 0
打印 上一主题 下一主题
收起左侧

TCP发送队列原理

[复制链接]
跳转到指定楼层
楼主
ID:90014 发表于 2015-9-13 20:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
TCP发送数据的时候并不是直接送出数据的,而是考虑了后续的数据一起发送所以,采用的是缓存队列机制。

一、API参数
1、
pcb指针
控制块记录这个连接的几乎所有的例如端口、IP地址、发送队列、接收窗口、序号等等自然不用细说。作为一个全局结构记录着你开的TCP所有的信息。所以只要找到他就可以知道和当前连接的所有有关结构的值。因此在程序调试过程中可以利用他来锁定相关的参数值等。所以这个指针就是指向了当前建立的连接。
2、 arg指针
显然这个是个万能的运载指针,这个是用来指向要发送的数据的,数据有两种一种是驻留在内存中也就是RAM中,另一种是驻留在FLASH中,也就是ROM中,在对待这两者最大区别是pbuf的分配,如果驻留在内存中,那么将会在RAM中开辟一块数据区并把arg指针指向的数据搬到这块内存中,前者不是协议栈管理而是用户的内存区,后者是协议栈管理的,用户无权操作。如果是ROM那么好了PBUF只有个头而已,并没有分配实际的数据区,他的数据区直接引用FLASH的地址,也就是一般const修饰的,编译器会把让他放入FLASH中去。
3、len
数据长度。要发送的数据有多么的长!请告诉他。
4、
apiflags
复制(RAM/ROM)和PSH标志
二、实现
1、如上参数传进来之后系统先要检查是否具备发送的条件:

1)、当前TCP状态是否允许做发送数据的动作?
2)、发送缓冲区的长度是都还够用?
3)、发送队列是否超出最大的定义长度?

如果全部通过则继续,否则自然不必说,返回错误代码给应用程序。
2、  
queuelen = pcb->snd_queuelen
取出当前发送队列记录里面的队列长度,、
3、找出来未发送队列中是否空?这里只讨论空的情况,也就是类似在第一次发送的情况。
所以  pcb->unsent = NULL是成立的。


4、判断是否copy应用数据到pbuf中。也就是说数据位置在在RAM还是ROM中?
如果RAM中
开始从RAM中分配一片承载len的pbuf。然后 do memcpy
如果是ROM中
那么引用指针到描述符中就OK无须copy。
然后在RAM中分配一个头部,然后连接起来
也就是头部+数据(指向ROM中)的结构。

5、queuelen += pbuf_clen(p)
计算出来pbuf数量。由于链表的结构所以实现超级简单
  while (p != NULL) {
    ++len;
    p = p->next;
  }
这样 queuelen 就是pbuf的数量了也就是p->next的数量,通常是RAMp->next=NULL就是 ++len=1了。

6、建立segment
动态从RAM中分配一块MEMP_TCP_SEG 长度的segment,
然后就是对这个TCP段进行填充了,比如远端的端口本地的端口序号、pbuf位置等。重要的是TCP的序号。也会被填入此种段域中记录。端口这些全部来自pcb中。
7、将段域写入pcb的usent队列中去。
queue = seg;
pcb->unsent = queue;
8、更新PCB相关项
  pcb->snd_lbb += len;
  pcb->snd_buf -= len;
下一个序号增加相应的数据长度。发送缓冲区减去已经用掉的字节长度。
9、将发送队列PBUF个数队列送入pcb的snd_queuelen。
pcb->snd_queuelen = queuelen;

10、 是否需要设置PSH?果如是设置之。

到这里就完成了对数据存入队列的全部过程了,当然还有一种情况就是队列不空的情况,那种情况在开始的时候要处理不过最终还是要计算出来到底有多少个pbuf在里面,是否超过设置最大值等依法炮制。
三:总结

对TCP数据的队列分清3个地方,

1、是发送缓冲区
2、tcp段队列
3、pbuf队列
第一个是以字节为单位的,他被永久的记录在pcb中的
pcb->snd_buf 中。
第二个是有多少个tcp段,他的单位是segment。他也被永久记录在 pcb->unsent ,
第三个个是有多少个pbuf单位是pbuf, 他也永久的记录在pcb->snd_queuelen 。

可见他们的关系基本上是找到PCB就能找到tcp段队列,找到pbuf队列,就能找到数据啦。而他们是按照先后顺序被连接起来的。应为几乎所有的结构形式都是以链表的形式存在。这样做个队列分分钟的事了就。
等真的发送数据的时候就会从tcp段队列取出来送到IP层逐层包装发送。

每次看源码我都怀着对原作者的极大崇敬,写程序的小朋友确实不容易啊! 理解!理解!










分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表