LwIP协议栈-TCP控制块(tcp_pcb)详解
LWIP协议TCP部分的结构体tcp_pcb的源代码如下:
struct tcp_pcb {
IP_PCB; //这是一个宏,描述了连接的IP相关信息,包括双方IP地址,TTL等信息
struct tcp_pcb *next; //用于连接各个TCP控制块的链表指针
enum tcp_state state; //TCP连接的状态,即为状态图中描述的那些状态
u8_t prio; //该控制块的优先级
void *callback_arg;//
u16_t local_port; //本地端口
u16_t remote_port; //远程端口
u8_t flags;// 附加状态信息,如连接是快速恢复、一个被延迟的 ACK是否被发送等
#define TF_ACK_DELAY (u8_t)0x01U //这些宏定义是为flags字段
#define TF_ACK_NOW (u8_t)0x02U //定义的掩码
#define TF_INFR (u8_t)0x04U
#define TF_RESET (u8_t)0x08U
#define TF_CLOSED (u8_t)0x10U
#define TF_GOT_FIN (u8_t)0x20U
#define TF_NODELAY (u8_t)0x40U
// 接收相关字段
u32_t rcv_nxt; //期望接收的下一个字节,即它向发送端ACK的序号
u16_t rcv_wnd; //接收窗口
u16_t rcv_ann_wnd; //通告窗口大小,较低版本中无该字段
u32_t tmr; // 该字段记录该PCB被创建的时刻
u8_t polltmr, pollinterval; // 三个定时器,后续讲解
u16_t rtime; //重传定时,该值随时间增加,当大于rto的值时则重传发生
u16_t mss; //最大数据段大小
//RTT估计相关的参数
u32_t rttest; //估计得到的500ms滴答数
u32_t rtseq; //用于测试RTT的包的序号
s16_t sa, sv; //RTT估计出的平均值及其时间差
u16_t rto; // 重发超时时间,利用前面的几个值计算出来
u8_t nrtx; // 重发的次数,该字段在数据包多次超时时被使用到,与设置rto的值相关
// 快速重传/恢复相关的参数
u32_t lastack; // 最大的确认序号,该字段不解
u8_t dupacks; // 上面这个序号被重传的次数
// 阻塞控制相关参数
u16_t cwnd; //连接的当前阻塞窗口
u16_t ssthresh; // 慢速启动阈值
// 发送相关字段
u32_t snd_nxt, // 下一个将要发送的字节序号
snd_max, // 最高的发送字节序号
snd_wnd, // 发送窗口
snd_wl1, snd_wl2, // 上次窗口更新时的数据序号和确认序号
snd_lbb; // 发送队列中最后一个字节的序号
u16_t acked; //
u16_t snd_buf; // 可用的发送缓冲字节数
u8_t snd_queuelen; // 可用的发送包数
struct tcp_seg *unsent; // 未发送的数据段队列
struct tcp_seg *unacked; // 发送了未收到确认的数据队列
struct tcp_seg *ooseq; // 接收到序列以外的数据包队列
#if LWIP_CALLBACK_API // 回调函数,部分函数在较低版本没定义
err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space);
err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); // 数据包接收回调函数
err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err);
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
err_t (* poll)(void *arg, struct tcp_pcb *pcb);
void (* errf)(void *arg, err_t err);
#endif
// 剩下的所有字段在较低版本中均未定义,用到时再讲解
u32_t keep_idle;
#if LWIP_TCP_KEEPALIVE
u32_t keep_intvl; // 保活定时器,用于检测空闲连接的另一端是否崩溃
u32_t keep_cnt;
#endif
u32_t persist_cnt; // 这两个字段可以使窗口大小信息保持不断流动
u8_t persist_backoff;
u8_t keep_cnt_sent;
};
先说说和接收数据相关的字段rcv_nxt, rcv_wnd, rcv_ann_wnd和数据发送的相关字段snd_nxt,snd_max,snd_wnd,acked。这些字段都和TCP中有名的滑动窗口协议有密切关系。如下图所示,连接的双方都维持一个窗口用于数据的发送。滑动窗口把整个序列分成三部分:左边的是发送了并且被确认的分组,窗口右边是还没发送的分组,窗口内部是待确认的分组,窗口内部又分成已经发送待确认的,和未发送但将立即发送。TCP是通过正面确认和重传技术来保证可靠性的,滑动窗口可以使发送方在收到前一个分组的确认信息前发送下一个分组,这样提高了网络的带宽利用率。
除了发送窗口外,TCP连接的双方还各自维护了一个接收窗口,如下图,接收方的接收窗口和发送方的发送窗口对比起来看看数据包的交互过程。
在接收方,rev_wnd表示了自己接收窗口的大小,它可以在给发送方的ACK包中通告自己的窗口大小值,发送方接收到该值后,就以此设子自己的发送窗口大小值snd_wnd。发送方的发送窗口内包含的数据发送序列是与ACK序号密切相关的,即它将ACK序号以后的snd_wnd个字节序号包括在窗口内。发送方的acked字段就表示已经接收到的最高的ACK序号,snd_nxt表示发送方即将发送数据的序号,acked与snd_nxt之间的数据表示已经被发送但还未接收到ACK,发送方也必须将他们包括在滑动窗内,以方便超时重发,snd_nxt到发送窗口末端表示还未发送的数据。snd_max表示不解,MARKKKKK一下,后面再来看看。在接收方,接收处于滑动窗内编号的数据,当某个序号以前的所有序号都已经接收到后,则接收方可以ACK该序号,并将接收窗口向后滑动。发送方也接收到该ACK后,也将自己的发送窗口向后滑动。在接收方,re_nxt表示希望接收到的下个字节序号,rev_ann_wnd表示对方通告的窗口大小,这里也表示不解。凌乱,凌乱。。。
与发送相关的还有cwnd字段,这就涉及到慢启动的概念了。当发送方接收到接收方的窗口通告后,并不会一下子把窗口内允许的数据全部发送出去,因为这样做的话可能由于中间路由器转发拥塞等原因,造成网络吞吐量不稳定,带宽利用率低等不良现象。发送端的做法是用cwnd字段保存一个拥塞窗口,发送方取拥塞窗口与通告窗口中的最小值作为发送上限,拥塞窗口初始值一般取1,并在每次收到接收方的一个ACK后加上一个值。关于慢启动还会在后续内容中讲解。
LwIP协议栈-TCP控制块(tcp_pcb)详解相关推荐
- TCP/IP 协议栈及 OSI 参考模型详解
TCP/IP 协议栈及 OSI 参考模型详解 转载地址:http://www.codeceo.com/article/tcp-ip-osi-model.html OSI参考模型 OSI RM:开放系统 ...
- TCP/IP网络协议栈:ARP协议详解
<TCP/IP网络协议栈:以太网数据包结构.802.3> <TCP/IP网络协议栈:ARP协议详解> <TCP / IP攻击:ARP缓存中毒的基本原理.TCP序列号预测和 ...
- 计算机网络知识详解之:TCP连接原理详解
网络知识详解之:TCP连接原理详解 计算机网络相关知识体系详解 网络知识详解之:TCP连接原理详解 网络知识详解之:HTTP协议基础 网络知识详解之:HTTPS通信原理剖析(对称.非对称加密.数字签名 ...
- TCP/IP协议详解---概述
工作之后,才发现以前在学校里学的东西忘得太快太干净了,现在需要一点点地捡起来了,要不然写几行程序会闹很多笑话会出现很多bug的.从今天开始,翻一翻<TCP/IP协议详解 卷1>这本书,希望 ...
- 《TCP IP协议 详解》思考总结 · 三
前言 这一篇文章主要围绕了IP协议,ICMP协议和UDP协议展开,希望可以在这里大概做一个总结,将<TCP/IP协议详解 卷一>书中TCP相关章节前面的内容做一个结束,在下一篇文章专心的去 ...
- FreeModbus开源协议栈的移植和详解(三)- RTU协议代码分析
FreeModbus开源协议栈的移植和详解(三) 目录 概述 一.RTU文件夹的文件 二.mbrtu.c文件 2.1数据类型说明 2.2函数说明 2.1eMBRTUInit()函数 2.2eMBRTU ...
- TCP /IP协议详解【转】
转自:https://www.jianshu.com/p/0cf648510bce?utm_campaign=maleskine&utm_content=note&utm_medium ...
- FreeModbus开源协议栈的移植和详解(一)- FreeModbus的下载和文件结构
FreeModbus开源协议栈的移植和详解(一) 引言 一.FreeModbus的获取 二.FreeModbus文件夹的介绍 三.Modbus文件夹介绍 四.小结 引言 很多做单片机或者嵌入式的朋友对 ...
- 4-4:TCP协议之TCP头部格式详解
文章目录 一:TCP头部格式详解 (1)4位首部长度 (2)序列号和确认应答号 A:可靠性问题 B:32位序号和确认号 (3)窗口大小 (4)标志位 (5)紧急指针 A:带外数据(out_of _ba ...
最新文章
- 【js】内置对象array的常见方法的使用
- c# 使用dotnetbar 控件绘制曲线图形
- 激光SLAM--标准数据集
- php5.3+for+linux,Centos 安装 nginx + php5.3
- python 文本相似度现状_python文本相似度分析
- 关于text-indent
- [Java][Android][Process] ProcessBuilder与Runtime区别
- NetworkX使用手册
- 综述:三维点云深度学习技术
- c#语言打印九九乘法表,C#打印九九乘法表
- python bt_linux平台使用Python制作BT种子并获取BT种子信息的方法
- Django1.9重写用户模型报错has no attribute 'USERNAME_FIELD'
- doc批量转成docx(doc batch convert docx)
- 安卓手机wifi速度测试软件,手机WiFi网络测速专家
- 为什么局部下降最快的方向就是梯度的负方向?
- 信息学切题记录:永远的A+B Problem(洛谷P1001)
- 电商系统中的商品模型的分析与设计
- pyplot 画多个图时搅合到了一起_【收藏贴】家里来了好些小朋友,什么游戏可以让孩子们玩到一起?...
- 在centos或者linux中安装完软件不能远程连接问题
- 关于ASoC中的aux设备及prefix(基于MTK mt6799 平台)
热门文章
- linux more命令 翻页,Linux系统中的翻页命令more和less使用教程
- WinHex Invalid file:user.txt.Do not proceed
- JavaScript基础之Ajax总结大全
- java 飞鸽传书 简易版 javafx实现
- 毕业5年跳槽了24次,换来6条血一样的职场教训
- Android开发:如果有选择,千万别去外包
- 如何部署linux服务器,CRAP-API——如何在Linux服务器部署CRAP-API教程
- shell高级编程笔记(第十章 循环和分支)
- 浅谈安卓Canvas,模拟心电图的绘制
- 怎么搜网站关联词,长尾词挖掘怎么做