首页 > 代码库 > 《TCP/IP详解卷2:实现》笔记--TCP:传输控制协议

《TCP/IP详解卷2:实现》笔记--TCP:传输控制协议

传输控制协议,即TCP,是一种面向连接的传输协议,为两端的应用程序提供可靠的端到端数据流传输服务,它完全不同于

无连接的、提供不可靠数据传输服务的UDP协议。

下图描述了各TCP函数与其他内核函数之间的关系,带阴影的椭圆分别表示我们将要讨论的9个主要的TCP函数。技术分享


1.TCP的protosw结构

下图列出了TCPprotosw结构的成员变量,它定义了TCP协议与系统内其他协议之间的交互接口。

技术分享


2.TCP的首部

tcphdr结构定义了tcp首部。下图给出了tcphdr结构的定义和TCP首部。

技术分享

技术分享

大多数的RFC文档中,相关书籍(包含卷1)和接下来要讨论的TCP实现代码,都把th_urp称为紧急指针。更准确的名称

应该是紧急数据偏移量。因为这个字段给出的16bit无符号整数值,与th_seg序号字段相加后,得到发送的紧急数据最后

一个八位组的32bit序号。

th_flags成员变量包含6个码元标志比特,通过下图中定义的名称读写。

技术分享

下图给出的ipovly结构定义了20字节长度的IP首部。通过前面的章节的讨论可知,尽管长度相同(20字节),但这个结构并

不是一个真正的IP首部。

技术分享


3.TCP的控制块

除了标准的Internet PCB外,TCP还有自己专用的控制块,tcpcb结构,而udp则不需要专用控制块,它的全部控制信息都

已包含在Internet PCB中。

TCP控制块较大,需占用140个字节,下图给出了TCP控制块的定义。

技术分享

技术分享

技术分享

下图给出了t_flags变量的可选值。

技术分享


4.TCP的状态迁移图

TCP协议根据连接上到达报文的不同类型,采取相应动作,协议规程可抽象为下图所示的有限状态变迁图。图中的各种状态

变迁组成了TCP有限状态机。尽管TCP协议允许从LISTEN状态直接变迁到SYN_SENT状态,但使用socket api编程时这种

变迁不可实现。(调用listen后不可以调用connect)

TCP控制块的成员变量t_state保存一个连接的当前状态。取值如下:

技术分享

图中还定义了tcp_outflags数组,保存了处于对应连接状态时tcp_output将使用的输出标志。

下图为TCP状态迁移图:

技术分享


5.TCP的序号

TCP连接上传输的每个数据字节,以及SYN、FIN等控制报文都被赋予一个32bit的序号。TCP首部的序号字段填充了报文段

第一个数据字节的32bit的序号,确认号字段填充了发送方希望接收的下一个序号。确认已正确接收了所有序号小于等于确认

号减1的数据字节。换言之,确认号是ACK发送方等待接收的下一序号。只有当序号首部的ACK标志置位时,确认序号才有效。

除了在主动打开首次发送SYN时或在某些RST报文段中,ACK标志总是被置位的。

1.序号取模运算

TCP必须处理一个问题是序号来自有限的32位取值空间:0~2^32-1,如果某个TCP连接传输的数据量超过2^32字节,序号从

2^32-1回绕到0,将出现重复序号。

即使传输数据量小于2^32字节,仍可能遇到相同的问题,因为连接的初始序号并不一定从0开始。各数据流方向上的初始序号

可以是0~2^32-1之间的任意值。

在tcp.h中,TCP序号定义为unsigned long,下图定了4个用于序号比较的宏。

技术分享

下面举例说明TCP序号的操作方式,假定序号只有3bit,0~7。下图列出了8个序号和相应的二进制补码。(为求无符号数的

二进制补码,将二进制中的所有0变成1,所有1变成0,再加上1),给出补码形式,是因为a-b = a+(b的补码)

技术分享

最后三栏分别是0-x,1-x和2-x的运算结果,其中最前面为0表示正数,为1表示负数。上面的1-x的结果表示:1大于0,1,6,7,

小于2,3,4,5.


6.tcp_init函数

系统初始化时,domaininit函数调用tcp的初始化函数tcp_init:
1.设定初始发送序号。
2.tcp internet PCB链表初始化。
3.计算最大协议首部长度。

《TCP/IP详解卷2:实现》笔记--TCP:传输控制协议