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协议详解(一)的更多相关文章

  1. TCP协议详解

    TCP协议详解 一.TCP协议 1.TCP 通过以下方式提供可靠性: ·  ◆ 应用程序分割为TCP认为最合适发送的数据块.由TCP传递给IP的信息单位叫做报文段. ·  ◆ 当TCP发出一个报文段后 ...

  2. 第3章 TCP协议详解

    第3章 TCP协议详解 3.1 TCP服务的特点 传输协议主要有两个:TCP协议和UDP协议,TCP协议相对于UDP协议的特点是 面向连接使用TCP协议通信的双方必须先建立连接,完成数据交换后,通信双 ...

  3. TCP协议详解7层和4层解析(美团,阿里) 尤其是三次握手,四次挥手 具体发送的报文和状态都要掌握

    如果想了解HTTP的协议结构,原理,post,get的区别(阿里面试题目),请参考:HTTP协议 结构,get post 区别(阿里面试) 这里有个大白话的解说,可以参考:TCP/IP协议三次握手和四 ...

  4. TCP协议详解(理论篇)

    TCP协议详解(理论篇) 2012-08-20      0个评论       作者:陈立龙 收藏    我要投稿 TCP协议详解(理论篇)   1.    与UDP不同的是,TCP提供了一种面向连接 ...

  5. linux高性能服务器编程 (三) --TCP协议详解

    第三章 IP协议详解 TCP协议是TCP/IP协议族中的另外一个重要的协议,与IP协议相比,TCP协议更高进应用层.一些重要的socket选项都和TCP协议相关.这一章主要从如下方面学习: 1)TCP ...

  6. 网络通信协议八之(传输层)TCP协议详解

    传输层协议 分段是为了提高传输效率,封装是指给每个数据段添加一个编号 端到端的传输是逻辑上的端到端,并不是真正意义上的发送方某层与接收方某层之间的传输 IP协议只是保证数据报文发送到目的地,为主机之间 ...

  7. 服务器编程入门(3)TCP协议详解

    问题聚焦:     本节从如下四个方面讨论TCP协议:     TCP头部信息:指定通信的源端端口号.目的端端口号.管理TCP连接,控制两个方向的数据流     TCP状态转移过程:TCP连接的任意一 ...

  8. TCP协议详解---上

    TCP头格式 注意以下几点: TCP的包是没有IP地址的,那是IP层上的事.但是有源端口和目标端口. 一个TCP连接需要四个元组来表示是同一个连接(src_ip, src_port, dst_ip, ...

  9. Linux 高性能服务器编程——TCP协议详解

    问题聚焦:     本节从如下四个方面讨论TCP协议:     TCP头部信息:指定通信的源端端口号.目的端端口号.管理TCP连接,控制两个方向的数据流     TCP状态转移过程:TCP连接的任意一 ...

随机推荐

  1. 灵感手环第一步——0.96寸OLED显示实验

    这算是我这个系列的第一篇博客吧.首先要解决的就是屏幕显示问题.我选择了目前新兴起的OLED显示模块. OLED(OrganicLightEmittingDiode),中文译作有机发光二极管,目前被广泛 ...

  2. SSH Secure Shell显示serverTomcat后台内容

    作为linux小白,仅仅有学一点记一点了: 部署server的时候.常常须要向本地一样查看控制台输出,在linux上能够通过查看日志输出替代,当然也能够通过命令让日志实时显示在命令窗体,这对用惯了wi ...

  3. JAVA入门[3]—Spring依赖注入

    Spring支持属性注入和构造器注入,它支持XML和注解两种方式.本文介绍Spring控制反转容器加载包含beans的XML文件,实现依赖注入. 一.创建bean实例 暂且抛开对象依赖,我们先看下如何 ...

  4. springboot 项目maven 打包错误

    Execution default of goal org.springframework.boot:spring-boot-maven-plugin:1.5.6.RELEASE:repackage ...

  5. 这么说吧,java线程池的实现原理其实很简单

    好处 : 线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配.调优和监控,有以下好处: 1.降低资源消耗: 2.提高响应速度: 3.提高线 ...

  6. pytho核心编程2-1中代码运行问题

    书籍是<python核心编程>第三版,学习环境py3.6 2-1 时间戳服务器 附源代码: from socket import * from time import ctime HOST ...

  7. this的理解

    this的理解 看了阮一峰的this讲解,下面是我的理解: 总结来说 this指向 调用this所在方法 的对象: 普通函数 例子1 function test(){ this.x = 1; cons ...

  8. 【java】java.util.Arrays类常用方法

    package Arrays类; import java.util.Arrays; public class TestArrays { public static void main(String[] ...

  9. 《跟我学IDEA》五、快捷键(编码利器)

    上一篇博文,我们学习了idea的一些模版配置,但是只有模版是不行的,一款编辑器如何能为我们灵活的使用,快捷键的功劳不用多说大家也明白.今天我们就来学习快捷键的配置以及一些常用的快捷键的介绍,为让家能更 ...

  10. rabbitMQ教程(三) spring整合rabbitMQ代码实例

    一.开启rabbitMQ服务,导入MQ jar包和gson jar包(MQ默认的是jackson,但是效率不如Gson,所以我们用gson) 二.发送端配置,在spring配置文件中配置 <?x ...