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. 怎样获取HTML5视频的持续时间

    HTML5视频的Bigger体验是非常令人振奋的,非常easy的道理,不用载入和依赖烦人的Flash或其它第三方插件来播放视频,也是大功一件.我们能够通过自己定义控件对视频进行显示和操控,当中一个常见 ...

  2. openstack初始化Glance数据库时报错解决方式

    环境为win7+virtualbox 中的centos6.5 安装Glance 的包 yum install openstack-glance python-glanceclient -y 配置Gla ...

  3. USACO Section 2.1 Healthy Holsteins

    /* ID: lucien23 PROG: holstein LANG: C++ */ #include <iostream> #include <fstream> #incl ...

  4. Selenium与phantomJS 登入豆瓣 有bug

    # -*- coding:utf-8 -*- from selenium import webdriver from selenium.webdriver.common.keys import Key ...

  5. License友好的前端组件合集

    在做Web开发过程中,不可避免的会用到各种UI组件.通常,我们并不会需要什么组件,都去自己开发的,网上有那么多好用的,我们为什么要自己造轮子呢?我通常只会在网上找不到合适的组件时,才会去自己开发一套. ...

  6. OPENSHIFT V3 免费部署 Java-Web

    OpenShift是红帽的云开发平台即服务(PaaS).自由和开放源码的云计算平台使开发人员能够创建.测试和运行他们的应用程序,并且可以把它们部署到云中.Openshift广泛支持多种编程语言和框架, ...

  7. ASP.NET Core 一步步搭建个人网站(3)_菜单管理

    上一章,我们实现了用户的注册和登录,登录之后展示的是我们的主页,页面的左侧是多级的导航菜单,定位并展示用户需要访问的不同页面.目前导航菜单是写死的,考虑以后菜单管理的便捷性,我们这节实现下可视化配置菜 ...

  8. 使用parcel替代webpack制作omi-tap插件

    Parcel 是一个零配置的网络应用打包工具, 适用于经验不同的开发者, 它利用多核处理提供了极快的速度.对比 webpack 最大的两个亮点: 零配置 极快速 omi 相关的插件都是基于 webpa ...

  9. SpringMVC框架(三)from标签(转)

    原文地址:http://blog.csdn.net/kutim/article/details/46682547 spring表单标签   <%@taglib uri="http:// ...

  10. 网口做trunk

    首先发现这个服务器的两个网口对应的交换机端口 ailixin-asw2960>en ailixin-asw2960#terminal monitor 查看端口的状态 ailixin-asw296 ...