TCP协议详解(一)
Tcp协议作为传输层的重要协议之一,想必每个稍有网络编程知识的人都不会感觉到陌生,三次握手/四次挥手这些基本概念也都是耳熟能详。但是当你们进行具体的网络编程的时候发现有很多事情并没有想象中的那么简单,会遇到很多·奇奇怪怪·的问题,说白了还是对于tcp协议的了解太过浮于表面。作为一个开发人员而言可能经常会去网上搜索一下有没有相关答案,但是即便问题解决了也是知其然不知其所以然。而不停的搜索答案试错是一种十分低劣的解决问题手法,个人观点认为当你遇见一个陌生的问题时如果时间允许的话先去了解它,这样解决问题会事半功倍(虽然前期效率可能会低一些)。
为了我们以后在网络编程的时候少挖一些坑,我们来仔细扒一扒tcp协议,下面的内容都引用于《计算机网络技术自上向下》第六版,话不多说开整。
一、tcp协议的数据结构

上图是tcp的段数据结构:
source port:数据来源端口 16bit
dest port:数据目的端口 16bit
sequence number:数据序列号 32bit
acknowledge number:数据应答编号 32bit
Header Length:头部长度 4bit
Unused:保留位 6bit
flage filed:标识位 6bit
receive window:接受窗口大小 16bit
internet checksum:校验位 16bit
urgent data pointer: 16bit
options:可选数据域 长度可变
data: 负载数据 长度可变
一般情况下options的长度为0,此时tcp协议数据段头部为20bytes,相比udp协议数据段头部多12bytes。这里要对数据序列号和确认号进行一下单独的说明,所谓的序列号与直观印象上的报文编号(1、2、3、4)这种不一样,我们举一个例子会直观一些比较:
例子: Alice 向 Bob 发送一个4M的文件:
假设Alice 的Seq起始值是 0,
第一个报文:
Seg0( Alice send to Bob): ....|Seq 0 | .... | Data (0~999 bytes)
Ack0 (Bob to Alice): ....| Ack 1000 ....
第二个报文
Seg1( Alice send to Bob): ....|Seq 1000 | Data (1000~2999 bytes)
Ack2 (Bob to Alice): .... Ack 3000 ....
... ...
细心的大佬就会发现了,这里的序列号和确认号实际上嘞是传输字节的序列,而不是报文的顺序,而确认号是接收方期待的下一个报文的序列号。
二、tcp的逻辑描述
我们在这里对tcp进行一个比较简单的逻辑上的描述,大家都知道网络层ip协议是管杀不管埋的,你报文能不能发送到?发送的完不完整?它一概不管,反正我是发了。所以tcp就在ip上封装了一层,来完成“全双工的可靠传输”--通过超时机制和冗余确认技术进行报文恢复,从而保证可靠传输。
tcp它不是一个停等协议,而是一个流传输协议。在整个tcp的传输流程中,有三个比较重要的事件:
Event 0:进程下发数据
Event 1:定时器超时
Event 2:Ack确认消息
下面附上书中的一段伪代码:
/* Assume sender is not constrained by TCP flow or congestion control, that data from above is less
than MSS in size, and that data transfer is in one direction only. */
NextSeqNum=InitialSeqNumber
SendBase=InitialSeqNumber
loop (forever) {
switch(event)
event: data received from application above
create TCP segment with sequence number NextSeqNum
if (timer currently not running)
start timer
pass segment to IP
NextSeqNum=NextSeqNum+length(data)
break;
event: timer timeout
retransmit not-yet-acknowledged segment with smallest sequence number
start timer
break;
event: ACK received, with ACK field value of y
if (y > SendBase) {
SendBase=y
if (there are currently any not-yet-acknowledged segments)
start timer
}
break;
} /* end of loop forever */
这段伪代码很好理解,主要就是处理我们上面说的三种重要的event:
event0 检查是否开启定时器 + 发送数据 + 序列号递增;
event1 从没有收到确认信息的最小序列号报文开始重传 + 开启定时器;
event2 更新sendBase+ 如果当前没有未被确认的seg就开启下一轮计时
ps:这里面start time后就会重新计时,timer只有一个,不是每发送一个报文就要开启一个timer。
逻辑上是不是很简单?这是那个搞得人头晕的tcp吗?没错,它的抽象逻辑就是这么简单,就是这么简单的逻辑,实现了我们现在网络的基石协议之一。当然这只是一个概述而已,实际情况要比这个复杂的多,不要误以为tcp实现起来很简单。我们要在这个简单模型的基础上不断的去完善它,我下面说三种情况,大家来思考一下有什么启发,理解一下这个模型有什么精妙之处,看看这个模型是怎么来保证可靠传输的:
我们假设这三种情况之前都是正常的!

第一种情况:
1)ACK缺失,timout时间内未收到确认;
2)timeout 触发event1,这时从序列号最小的未被确认报文重传 seq92,重启timer;

第二种情况比较复杂那么一点点:
1)我们可以看到在第一个timeout 内 Seq 92、Seq 100的Ack并未返回;
2)当timeout时 event1 被触发,我们重传了Seq 92 ,重置了timer;
3) 在 第二次time out 之前 Ack 100和 Ack 120收到 ,此时没有未被确认的segments(这样我们就不需要重传seq100), 重置timer;
4)再次收到 Ack 120
ps:这里面有老铁会迷惑:我在第二个timeout中重传了Seq92,为对方返回的是Ack 120? 这个问题容我等下解答。

第三种情况:
1)发送seq 92和 Seq 100
2)ack100丢失
3)在timeout 前Ack120收到,此时无需进行重传。
ps:这里又多了个疑点,为啥Ack100丢失不用重传Seq92?明明在情况一种需要重传啊。
这都在下一回合解答。
TCP协议详解(一)的更多相关文章
- TCP协议详解
TCP协议详解 一.TCP协议 1.TCP 通过以下方式提供可靠性: · ◆ 应用程序分割为TCP认为最合适发送的数据块.由TCP传递给IP的信息单位叫做报文段. · ◆ 当TCP发出一个报文段后 ...
- 第3章 TCP协议详解
第3章 TCP协议详解 3.1 TCP服务的特点 传输协议主要有两个:TCP协议和UDP协议,TCP协议相对于UDP协议的特点是 面向连接使用TCP协议通信的双方必须先建立连接,完成数据交换后,通信双 ...
- TCP协议详解7层和4层解析(美团,阿里) 尤其是三次握手,四次挥手 具体发送的报文和状态都要掌握
如果想了解HTTP的协议结构,原理,post,get的区别(阿里面试题目),请参考:HTTP协议 结构,get post 区别(阿里面试) 这里有个大白话的解说,可以参考:TCP/IP协议三次握手和四 ...
- TCP协议详解(理论篇)
TCP协议详解(理论篇) 2012-08-20 0个评论 作者:陈立龙 收藏 我要投稿 TCP协议详解(理论篇) 1. 与UDP不同的是,TCP提供了一种面向连接 ...
- linux高性能服务器编程 (三) --TCP协议详解
第三章 IP协议详解 TCP协议是TCP/IP协议族中的另外一个重要的协议,与IP协议相比,TCP协议更高进应用层.一些重要的socket选项都和TCP协议相关.这一章主要从如下方面学习: 1)TCP ...
- 网络通信协议八之(传输层)TCP协议详解
传输层协议 分段是为了提高传输效率,封装是指给每个数据段添加一个编号 端到端的传输是逻辑上的端到端,并不是真正意义上的发送方某层与接收方某层之间的传输 IP协议只是保证数据报文发送到目的地,为主机之间 ...
- 服务器编程入门(3)TCP协议详解
问题聚焦: 本节从如下四个方面讨论TCP协议: TCP头部信息:指定通信的源端端口号.目的端端口号.管理TCP连接,控制两个方向的数据流 TCP状态转移过程:TCP连接的任意一 ...
- TCP协议详解---上
TCP头格式 注意以下几点: TCP的包是没有IP地址的,那是IP层上的事.但是有源端口和目标端口. 一个TCP连接需要四个元组来表示是同一个连接(src_ip, src_port, dst_ip, ...
- Linux 高性能服务器编程——TCP协议详解
问题聚焦: 本节从如下四个方面讨论TCP协议: TCP头部信息:指定通信的源端端口号.目的端端口号.管理TCP连接,控制两个方向的数据流 TCP状态转移过程:TCP连接的任意一 ...
随机推荐
- java傻瓜简单100%一定看的懂新手安装教程
1.java官网 最新的不是很稳定 http://www.oracle.com/technetwork/java/javase/downloads/index.html 一直点下一步就可以,但别忘 ...
- DotNetCore跨平台~xUnit生成xml报告
在CI/CD流行至极的今天,你的项目没有自动化测试绝对是不可以接受的,在进行自动化部署和持续集成时,我们的dotnet core项目也是可以实现自动化的,之前说过gitlab,jenkins对持续集成 ...
- Java-----关于线程池的使用
关于线程的相关概念不在此阐述,请百度或谷歌之 对于学习线程来说,我认为从代码开始学习比较好,前提是有一定的技术的积累,否则请关闭不用再看了~ 线程池四种实现方式. ①可缓存线程池,如果线程池长度超过处 ...
- C++11新特性应用--介绍几个新增的便利算法(不更改容器中元素顺序的算法)
总所周知.C++ STL中有个头文件,名为algorithm.即算法的意思. The header<algorithm>defines a collection of functions ...
- IIS中遇到无法预览的问题(HTTP 错误 401.3 - Unauthorized 因为 Web server上此资源的訪问控制列表(ACL)配置或加密设置,您无权查看此文件夹或页面。)
在IIS中 依次运行例如以下操作: 站点--编辑权限--共享(为了方便能够直接将分享对象设置为everyone)--安全(直接勾选 everyone )--应用--确定.
- 使用Logstash来实时同步MySQL数据到ES
上篇讲到了ES和Head插件的环境搭建和配置,也简单模拟了数据作测试 本篇我们来实战从MYSQL里直接同步数据 一.首先下载和你的ES对应的logstash版本,本篇我们使用的都是6.1.1 下载后使 ...
- intellij idea的安装步骤---经典
安装IntelliJ IDEA 一.安装JDK 1 下载最新的jdk,这里下的是jdk-8u66 2 将jdk安装到默认的路径C:\Program Files\Java目录下 二.安装IntelliJ ...
- charles支持https抓包配置
自从公司站点全部启用https后,使用charles就不能像以前那样愉快的抓包啦!不过没关系,这里教你怎么配置charles,使其支持https抓包.之前有一篇介绍charles的使用,参考这篇:ht ...
- 微信小程序——轮播图实现
小程序的轮播图,也就是他其中的一个控件可以算是直接上代码: 这是WXML 页面 代码: <view class='carousel_div'> <swiper class=" ...
- NodeJS学习笔记(二)
对NodeJS的基本配置了解之后,现在需要解决一些显示问题,大致有以下问题 1.与PHP框架Laravel的密码验证系统相适应 2.异步调用的常见编程问题:Promise和Ev ...