1、TCP的特点:

基于字节流
面向连接
可靠传输
缓冲传输
全双工
流量控制

2、头部格式和说明

图源百度。如下图示,就是TCP包的头部结构。可以看到这个头部最少有4x5=20个字节。

另外还需要理解TCP协议是承载在IP协议中的。关于IP协议可以参考:http://www.cnblogs.com/xcywt/p/8067521.html

源端口号和目的端口号:再加上Ip首部的源IP地址和目的IP地址可以唯一确定一个TCP连接
数据序号:表示在这个报文段中的第一个数据字节序号
确认序号:仅当ACK标志为1时有效。确认号表示期望收到的下一个字节的序号(这个下面再详细分析)
偏移:就是头部长度,有4位,跟IP头部一样,以4字节为单位。最大是60个字节
保留位:6位,必须为0
6个标志位:
URG-紧急指针有效
ACK-确认序号有效
PSH-接收方应尽快将这个报文交给应用层
RST-连接重置
SYN-同步序号用来发起一个连接
FIN-终止一个连接

窗口字段:16位,代表的是窗口的字节容量,也就是TCP的标准窗口最大为2^16 - 1 = 65535个字节(这个下面再详细分析)

校验和:源机器基于数据内容计算一个数值,收信息机要与源机器数值 结果完全一样,从而证明数据的有效性。检验和覆盖了整个的TCP报文段:这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证的。

紧急指针:是一个正偏移量,与序号字段中的值相加表示紧急数据最后一个字节的序号。TCP的紧急方式是发送端向另一端发送紧急数据的一种方式
选项与填充(必须为4字节整数倍,不够补0):
最常见的可选字段的最长报文大小MSS(Maximum Segment Size),每个连接方通常都在一个报文段中指明这个选项。它指明本端所能接收的最大长度的报文段。
该选项如果不设置,默认为536(20+20+536=576字节的IP数据报)

3、TCP如何保证可靠性

1)应用数据被分割成TCP认为最合适发送的数据块。称为段(Segment)传递给IP层
2)当TCP发出一个段后,它会启动一个定时器,等待目的端确认收到这个报文段。若没有及时收到确认,将重新发送这个报文段
3)当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送的,通常将推迟几分之一秒。
4)TCP将保持它首部和数据的校验和,这是一个端到端的校验和,目的是检测数据在传输过程中的任何变化。如果收到段的校验和有差错,TCP将丢弃这个报文也不进行确认(对方就会重复发送了)。
5)TCP承载与IP数据报来传输,而IP数据报可能会失序,所以TCP的报文段到达时也可能会失序。但是TCP收到数据后会重新排序到正确的顺序(通过序号)。
6)IP数据报会发生重复,TCP的接收端必须丢弃重复是数据
7)TCP还能提供流量控制,TCP连接的每一方都有一定大小的缓冲空间

4、滑动窗口协议(也就是对包头中窗口字段的理解)

参考1:https://www.cnblogs.com/ulihj/archive/2011/01/06/1927613.html

参考2:http://blog.chinaunix.net/uid-26275986-id-4109679.html

先上两个概念:
通告接收窗口(rwnd):预防应用程序发送的数据超过对方的缓冲区,接收方使用的流量控制。
拥塞窗口(cwnd):预防应用程序发送的数据超过了网络所能承载的能力。发送方使用的流量控制。
发送窗口:就是指上面两者的较小值

由于TCP的全双工的,所以其实TCP双方各自都维护一个发送窗口和接收窗口。

假设是主机A发送给主机B
A和B都会维护一个数据帧的序列,这个序列称为窗口。发送方的窗口大小由接收方确定。目的在于控制发送速度。以免接收方的缓存不够大而导致溢出,同时流量控制也可以避免网络拥塞。
这里其实是指A的发送窗口。

假设A发送了很多段给B,序号是1-10.这些段会处于种状态:
1)已发送,已确认
2)已发送,未确认
3)等待发送
4)不允许发送

正常情况下,每个段都会由4状态->3状态->2状态->1状态。而窗口就是指处于状态2和状态3的总数。
由2状态->1状态的时候,窗口就会往后滑动一下,表示最近那个4状态的段可以变成3状态了。
如果接收方一直不确认,那么处于4状态的段将永远不会被发送。
当窗口满了的时候,4状态的段将不会变成3状态。从而达到了控制发送速度的作用。

就像上图一样,123处于1状态,456处于2状态,789处于3状态,10以后的处于4状态。而窗口就是指哪个框起来的。这里为6。

随着发送段被逐一的确认,这个窗口会往右滑动。

就像一个水池,总体积V,进水速度是s1,出水速度s2。当水池满了就不能再注入了,强行注入会溢出丢失。窗口就是那个水池。

滑动窗口实现面向流的可靠性:

1)最基本的传输可靠性来源于确认重传机制
2)滑动窗口的可靠性也是建立在确认重传机制上的
3)发送窗口只有收到目的端口对本段发送窗口内字节的ACK确认,才会移动发送串口的左边界。
4)接收窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有段未收到确认,但是收到了后面段的情况下,窗口不会移动,也不对后续段进行确认。以此确保发送端会对这个数据重传。

5、关于包头中确认号ack的理解

确认序号:仅当ACK标志为1时有效。确认号表示期望收到的下一个字节的序号

这里是拿三次握手之后,开始传输数据了进行分析。

服务器向客户端发送一个数据包后,客户端收到了这个数据包,会向服务器发送一个确认数据包。

传输数据的简要过程如下:

1)发送数据:服务器向客户端发送一个带有数据的数据包。该数据包中的序列号和确认号与建立连接第三步的数据包找那个的序列号和确认号相同。

2)确认收到:客户端收到该数据包,向服务器发送一个确认数据包。该数据包中,序列号是为上一个数据包中的确认号值。

而确认号为服务器发送的上一个数据包中的序列号+该数据包中所带数据的大小。

回复确认收到的ack = 收到了序列号 + 数据的大小(同时也表示下一次期望收到的序号)

这里我们直接拿Wireshark抓包进行分析:

实例1:客户端给服务器发送了”xcychongyong” 共13个字节。

先看,服务器收到的,也就是客户端发送的:seq是10,数据长度是13.

再来看服务器发送给客户端的确认包:根据上面的说明。ack应该是10 + 13 = 23

实例2:

如下图,208(就是192.168.0.208)一共向182(就是192.168.0.182)发送了6组数据。

过滤条件:tcp and (ip.src==192.168.0.182 or ip.dst==192.168.0.182)

对于182来说:

第一次回应时ack是4,结果208下一次发送的序号就是4。

第二次回应时ack是10,结果208下一次发送的序号就是10。

第三次回应时ack是19,结果208下一次发送的序号就是19。

以此类推…

再来分析一个互相发送的:

如图,一共发送了5次:

第一次182发给208,发的长度是7,seq是1.所以208回复的ack是8。也相当于告诉182:“182,你下次发的时候,序号就从8开始”。看第2个红框,seq就是8.

第二次208发给182,发的长度是11,seq是1,所以182回复的ack是12。也相当于告诉208:“208,你下次发的时候,序号就从12开始”。看第2个绿框,seq就是12.

同理,

182再发送一次给208,seq应该是17

208再发送一次给182,seq应该是33

ack表示期望下次接收到的序号。

那么ack是如何算出来的呢,就是通过收到的序号,和数据长度相加得来。

假设A收到B过来的数据(seq = 5,len = 15)。len表示数据长度。

那么A就会回复B,“刚才的数据我已经收到了,你接下来就发序号为20的包给我吧”。这样就保证了数据不会乱序。

综上,确认号就是下一次将要收到包的序号。同时也等于发送方的序号+数据长度(确认号在ACK标志位有效时才有用。)

TCP头部分析与确认号的理解的更多相关文章

  1. TCP 序列号和确认号是如何变化的?

    大家好,我是小林. 在网站上回答了很多人的问题,我发现很多人对 TCP 序列号和确认号的变化都是懵懵懂懂的,只知道三次握手和四次挥手过程中,ACK 报文中确认号要 +1,然后数据传输中 TCP 序列号 ...

  2. 转 TCP中的序号和确认号

    在网络分析中,读懂TCP序列号和确认号在的变化趋势,可以帮助我们学习TCP协议以及排查通讯故障,如通过查看序列号和确认号可以确定数据传输是否乱 序.但我在查阅了当前很多资料后发现,它们大多只简单介绍了 ...

  3. TCP序列号和确认号

    TCP序列号和确认号详解 在网络分析中,读懂TCP序列号和确认号在的变化趋势,可以帮助我们学习TCP协议以及排查通讯故障,如通过查看序列号和确认号可以确定数据传输是否乱序.但我在查阅了当前很多资料后发 ...

  4. TCP头部结构

    3.2 TCP头部结构 TCP头部信息出现在每个TCP报文段中,用于指定通信的源端端口,目的端端口,管理TCP连接等,本节详细介绍TCP的头部结构,包括固定头部结构和头部选项. 3.2.1 TCP固定 ...

  5. 韩顺刚-tcp报文头协议详细分析第一包数据:序号是0,发送数据的长度是0,因为没有收到对端的数据,所以确认号是0, Syn的标志位设置成1,这里没有发送的数据,只发送TCP的20个字节的头部

    TCP报文段首部格式 大部分TCP报文头部都是20个字节,有的数据包要加上选项. 上面一行代表4个字节,源端口和目的端口都是2个字节. TCP协议是面向字节流的协议 TCP是一段一段分块的发送数据的 ...

  6. 理解TCP序列号(Sequence Number)和确认号(Acknowledgment Number)

    原文见:http://packetlife.net/blog/2010/jun/7/understanding-tcp-sequence-acknowledgment-numbers/ from:ht ...

  7. TCP:WireShark分析,序列号Seq和确认号Ack

    转载自 http://blog.csdn.net/a19881029/article/details/38091243 序列号为当前端成功发送的数据位数,确认号为当前端成功接收的数据位数,SYN标志位 ...

  8. [转] 理解TCP序列号(Sequence Number)和确认号(Acknowledgment Number)

    点击阅读原译文 原文见:http://packetlife.net/blog/2010/jun/7/understanding-tcp-sequence-acknowledgment-numbers/ ...

  9. TCP头部格式详解,附Wireshark对TCP头部抓包分析

    TCP之所以能为数据通讯提供可靠的传输,主要在于TCP数据包头部功能非常多. 那么,我们先来看看TCP头部格式(RFC 793.1323定义了TCP头部): TCP头部格式中的内容解析如下:(文末还有 ...

随机推荐

  1. HDU 5791 Two(训练题002 F)

    Description Alice gets two sequences A and B. A easy problem comes. How many pair of sequence A' and ...

  2. POJ 3468 A Simple Problem with Integers(树状数组区间更新)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 97217   ...

  3. Game of Connections

    Game of Connections Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...

  4. pycharm安装激活

    我的版本是pycharm-professional-2016.3.3 总体的安装步骤基本没什么,就是一直下一步,下一步就行了. 重要的最后的注册,找了一堆版本,最后用的server,注册成功. 注册码 ...

  5. 利用 bat 批量处理命令实现手动控制mysql /Oracle 服务的开启和关闭

    利用 bat 批量处理命令实现手动控制mysql /Oracle 服务的开启和关闭 因为最近在学习数据库的知识,主要学习的是oracle 数据库,然而好巧啊,java也是在学习,我们老师现在要我们做一 ...

  6. stm32l053r8 nucelo板的串口实验

    stm32cubel0的HAL驱动实例中,基于stm32l53R8  nucelo板的官方串口通讯例程,是使用USART1实现在两块stm32l053r8 nucelo板间通讯.而在实际中,笔者手中只 ...

  7. ZooKeeper入门

    ZooKeeper简介 ZooKeeper是一个构建在Paxos算法上的高可用的分布式数据管理与系统协调框架,提供了一系列原语集,更上层的应用可以用它来实现同步,配置管理,名称服务,Master选举, ...

  8. python中print()函数的“,”与java中System.out.print()函数中的“+”

    python中的print()函数和java中的System.out.print()函数都有着打印字符串的功能. python中: print("hello,world!") 输出 ...

  9. Java提高十五:容器元素比较Comparable&Comparator深入分析

    我们经常用容器来存放元素,通常而言我们是不关系容器中的元素是否有序,但有些场景可能要求容器中的元素是有序的,这个时候用ArrayList  LinkedList  Hashtable HashMap ...

  10. setTimeout和setInterval的使用

    引自(http://www.cnblogs.com/qiantuwuliang/archive/2009/06/20/1507304.html) 这两个方法都可以用来实现在一个固定时间段之后去执行Ja ...