趣谈网络协议
刘超
网易研究院云计算技术部首席架构师
立即订阅
39583 人已学习
课程目录
已完结 51 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 想成为技术牛人?先搞定网络协议!
免费
第一模块 通信协议综述 (4讲)
第1讲 | 为什么要学习网络协议?
第2讲 | 网络分层的真实含义是什么?
第3讲 | ifconfig:最熟悉又陌生的命令行
第4讲 | DHCP与PXE:IP是怎么来的,又是怎么没的?
第二模块 底层网络知识详解:从二层到三层 (5讲)
第5讲 | 从物理层到MAC层:如何在宿舍里自己组网玩联机游戏?
第6讲 | 交换机与VLAN:办公室太复杂,我要回学校
第7讲 | ICMP与ping:投石问路的侦察兵
第8讲 | 世界这么大,我想出网关:欧洲十国游与玄奘西行
第9讲 | 路由协议:西出网关无故人,敢问路在何方
第二模块 底层网络知识详解:最重要的传输层 (4讲)
第10讲 | UDP协议:因性善而简单,难免碰到“城会玩”
第11讲 | TCP协议(上):因性恶而复杂,先恶后善反轻松
第12讲 | TCP协议(下):西行必定多妖孽,恒心智慧消磨难
第13讲 | 套接字Socket:Talk is cheap, show me the code
第二模块 底层网络知识详解:最常用的应用层 (4讲)
第14讲 | HTTP协议:看个新闻原来这么麻烦
第15讲 | HTTPS协议:点外卖的过程原来这么复杂
第16讲 | 流媒体协议:如何在直播里看到美女帅哥?
第17讲 | P2P协议:我下小电影,99%急死你
第二模块 底层网络知识详解:陌生的数据中心 (6讲)
第18讲 | DNS协议:网络世界的地址簿
第19讲 | HTTPDNS:网络世界的地址簿也会指错路
第20讲 | CDN:你去小卖部取过快递么?
第21讲 | 数据中心:我是开发商,自己拿地盖别墅
第22讲 | VPN:朝中有人好做官
第23讲 | 移动网络:去巴塞罗那,手机也上不了脸书
第三模块 热门技术中的应用:云计算中的网络 (5讲)
第24讲 | 云中网络:自己拿地成本高,购买公寓更灵活
第25讲 | 软件定义网络:共享基础设施的小区物业管理办法
第26讲 | 云中的网络安全:虽然不是土豪,也需要基本安全和保障
第27讲 | 云中的网络QoS:邻居疯狂下电影,我该怎么办?
第28讲 | 云中网络的隔离GRE、VXLAN:虽然住一个小区,也要保护隐私
第三模块 热门技术中的应用:容器技术中的网络 (3讲)
第29讲 | 容器网络:来去自由的日子,不买公寓去合租
第30讲 | 容器网络之Flannel:每人一亩三分地
第31讲 | 容器网络之Calico:为高效说出善意的谎言
第三模块 热门技术中的应用:微服务相关协议 (5讲)
第32讲 | RPC协议综述:远在天边,近在眼前
第33讲 | 基于XML的SOAP协议:不要说NBA,请说美国职业篮球联赛
第34讲 | 基于JSON的RESTful接口协议:我不关心过程,请给我结果
第35讲 | 二进制类RPC协议:还是叫NBA吧,总说全称多费劲
第36讲 | 跨语言类RPC协议:交流之前,双方先来个专业术语表
第四模块 网络协议知识串讲 (4讲)
第37讲 | 知识串讲:用双十一的故事串起碎片的网络协议(上)
第38讲 | 知识串讲:用双十一的故事串起碎片的网络协议(中)
第39讲 | 知识串讲:用双十一的故事串起碎片的网络协议(下)
第40讲 | 搭建一个网络实验环境:授人以鱼不如授人以渔
答疑与加餐 (9讲)
协议专栏特别福利 | 答疑解惑第一期
协议专栏特别福利 | 答疑解惑第二期
协议专栏特别福利 | 答疑解惑第三期
协议专栏特别福利 | 答疑解惑第四期
协议专栏特别福利 | 答疑解惑第五期
加餐1 | 测一测:这些网络协议你都掌握了吗?
加餐2 | 创作故事:我是如何创作“趣谈网络协议”专栏的?
加餐3 | “趣谈网络协议”专栏食用指南
第2季回归 | 这次我们来“趣谈Linux操作系统”
结束语 (1讲)
结束语 | 放弃完美主义,执行力就是限时限量认真完成
趣谈网络协议
登录|注册

第11讲 | TCP协议(上):因性恶而复杂,先恶后善反轻松

刘超 2018-06-11
上一节,我们讲的 UDP,基本上包括了传输层所必须的端口字段。它就像我们小时候一样简单,相信“网之初,性本善,不丢包,不乱序”。
后来呢,我们都慢慢长大,了解了社会的残酷,变得复杂而成熟,就像 TCP 协议一样。它之所以这么复杂,那是因为它秉承的是“性恶论”。它天然认为网络环境是恶劣的,丢包、乱序、重传,拥塞都是常有的事情,一言不合就可能送达不了,因而要从算法层面来保证可靠性。

TCP 包头格式

我们先来看 TCP 头的格式。从这个图上可以看出,它比 UDP 复杂得多。
首先,源端口号和目标端口号是不可少的,这一点和 UDP 是一样的。如果没有这两个端口号。数据就不知道应该发给哪个应用。
接下来是包的序号。为什么要给包编号呢?当然是为了解决乱序的问题。不编好号怎么确认哪个应该先来,哪个应该后到呢。编号是为了解决乱序问题。既然是社会老司机,做事当然要稳重,一件件来,面临再复杂的情况,也临危不乱。
还应该有的就是确认序号。发出去的包应该有确认,要不然我怎么知道对方有没有收到呢?如果没有收到就应该重新发送,直到送达。这个可以解决不丢包的问题。作为老司机,做事当然要靠谱,答应了就要做到,暂时做不到也要有个回复。
TCP 是靠谱的协议,但是这不能说明它面临的网络环境好。从 IP 层面来讲,如果网络状况的确那么差,是没有任何可靠性保证的,而作为 IP 的上一层 TCP 也无能为力,唯一能做的就是更加努力,不断重传,通过各种算法保证。也就是说,对于 TCP 来讲,IP 层你丢不丢包,我管不着,但是我在我的层面上,会努力保证可靠性。
这有点像如果你在北京,和客户约十点见面,那么你应该清楚堵车是常态,你干预不了,也控制不了,你唯一能做的就是早走。打车不行就改乘地铁,尽力不失约。
接下来有一些状态位。例如 SYN 是发起一个连接,ACK 是回复,RST 是重新连接,FIN 是结束连接等。TCP 是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更。
不像小时候,随便一个不认识的小朋友都能玩在一起,人大了,就变得礼貌,优雅而警觉,人与人遇到会互相热情的寒暄,离开会不舍的道别,但是人与人之间的信任会经过多次交互才能建立。
还有一个重要的就是窗口大小。TCP 要做流量控制,通信双方各声明一个窗口,标识自己当前能够的处理能力,别发送的太快,撑死我,也别发的太慢,饿死我。
作为老司机,做事情要有分寸,待人要把握尺度,既能适当提出自己的要求,又不强人所难。除了做流量控制以外,TCP 还会做拥塞控制,对于真正的通路堵车不堵车,它无能为力,唯一能做的就是控制自己,也即控制发送的速度。不能改变世界,就改变自己嘛。
作为老司机,要会自我控制,知进退,知道什么时候应该坚持,什么时候应该让步。
通过对 TCP 头的解析,我们知道要掌握 TCP 协议,重点应该关注以下几个问题:
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《趣谈网络协议》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(123)

  • code4j 置顶
    老师您好,昨天阿里云出故障,恢复后,我们调用阿里云服务的时后出现了调用出异常 connection reset。netstat看了下这个ip发现都是timewait,链接不多,但是始终无法连接放对方的服务。按照今天的内容,难道是我的程序关闭主动关闭链接后没有发出最后的ack吗?之前都没有问题,很不解
    2018-06-28
    2
    24
  • 进阶的码农 置顶
    状态机图里的不加粗虚线看不懂什么意思 麻烦老师点拨下

    作者回复: 其他非主流过程

    2018-06-11
    9
  • Colin.Tao
    旧书不厌百回读,熟读深思子自知啊。

    再一次认识下TCP这位老司机,这可能是我读过的最好懂的讲TCP的文章了。同时有了一个很爽的触点,我发现但凡复杂点儿的东西,状态数据都复杂很多。还有一个,也是最重要的,我从TCP中再一次认识到了一个做人的道理,像孔子说的:“不怨天,不尤人”。人与人相处,主要是“我,你,我和你的关系”这三个处理对象,“你”这个我管不了,“我”的成长亦需要时间,我想到的是“我和你的关系”,这个状态的维护,如果能“无尤”,即不抱怨。有时候自己做多点儿,更靠谱点,那人和人的这个连接不是会更靠谱么?这可能是我从TCP这儿学到的最棒的东西了。

    感谢老师的讲解,让我有了新的想法和收获。

    作者回复: 赞

    2018-09-23
    1
    45
  • krugle
    流量控制和拥塞控制什么区别

    作者回复: 一个是对另一端的,一个是针对网络的

    2018-08-17
    43
  • monkay
    如果是建立链接了,数据传输过程链接断了,客户端和服务器端各自会是什么状态?
    或者我可以这样理解么,所谓的链接根本是不存在的,双方握手之后,数据传输还是跟udp一样,只是tcp在维护顺序、流量之类的控制

    作者回复: 是的,连接就是两端的状态维护,中间过程没有所谓的连接,一旦传输失败,一端收到消息,才知道状态的变化

    2018-06-11
    1
    41
  • Jerry银银
    看了大家的留言,很有感触,对于同一个技术点,技术的原理是一样的,可是每个人都有自己的理解,和自己独有的知识关联,因为每个人过往所积累的知识体系有所不同。

    我对TCP,甚至整个网络知识,喜欢用「信息论」中的一些理论去推演它们。我觉得在现在和未来的时代,「信息论」是一把利器。

    信息论中,有个很重要的思想:要想消除信息的不确定性,就得引入信息。将这个思想应用到TCP中,很容易理解TCP的三次握手和四次挥手的必要性:它们的存在以及复杂度,就是为了消除不确定性,这里我们叫「不可靠性」吧。拿三次握手举例:
    为了描述方便,将通信的两端用字母A和B替代。A要往B发数据,A要确定两件事:
    1. B在“那儿”,并且能接受数据 —— B确实存在,并且是个“活人”,能听得见
    2. B能回应 —— B能发数据,能说话
    为了消除这两个不确定性,所以必须有前两次握手,即A发送了数据,B收到了,并且能回应——“ACK”

    同样的,对于B来说,它也要消除以上两个不确定性,通过前两次握手,B知道了A能说,但是不能确定A能听,这就是第三次握手的必要性。

    当然你可能会问,增加第四次握手有没有必要?从信息论的角度来说,已经不需要了,因为它的增加也无法再提高「确定性」
    2019-05-17
    35
  • Ender0224
    多谢分享,精彩。扫除了我之前很多的疑问。tcp连接的断开比建立复杂一些,本质上是因为资源的申请(初始化)本身就比资源的释放简单,以c++为例,构造函数初始化对象很简单,而析构函数则要考虑所有资源安全有序的释放,tcp断连时序中除了断开这一重要动作,另外重要的潜台词是“我要断开连接了 你感觉把收尾工作做了”

    作者回复: 谢谢

    2018-06-11
    24
  • Adolph
    为什么要三次握手
    三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。

    第一次握手:Client 什么都不能确认;Server 确认了对方发送正常

    第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己接收正常,对方发送正常

    第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送接收正常

    所以三次握手就能确认双发收发功能都正常,缺一不可。
    2019-03-27
    23
  • Ender0224
    评论区不能互评,如下两个问题是我的看法,不对请指出 多谢


    我们做一个基于tcp的“物联网”应用(中国移动网络),如上面所说tcp层面已经会自动重传数据了,业务层面上还有必要再重传吗?如果是的话,业务需要多久重传一次?

    --- TCP的重传是网络层面和粒度的,业务层面需要看具体业务,比如发送失败可能对端在重启,一个重启时间是1min,那就没有必要每秒都发送检测啊.

    1、‘序号的起始序号随时间变化,...重复需要4个多小时’,老师这个重复时间怎么计算出来的呢?每4ms加1,如果有两个TCP链接都在这个4ms内建立,是不是就是相同的起始序列号呢。
    答:序号的随时间变化,主要是为了区分同一个链接发送序号混淆的问题,两个链接的话,端口或者IP肯定都不一样了.2、报文最大生存时间(MSL)和IP协议的路由条数(TTL)什么关系呢,报文当前耗时怎么计算?TCP层有存储相应时间?
    答:都和报文生存有关,前者是时间维度的概念,后者是经过路由跳数,不是时间单位.

    作者回复: 赞

    2018-06-14
    20
  • 小田
    人大了,就变得礼貌,优雅而警觉
    2018-06-12
    18
  • eason2017
    老师好,我看书中说是计数器每4微妙就加1的。

    作者回复: 赞

    2018-07-04
    15
  • 零一
    可以用 netstat 或者 lsof 命令 grep 一下 establish listen close_wait 等这些查看
    2018-06-11
    13
  • 天天
    流量控制是照顾通信对象
    拥塞控制是照顾通信环境

    作者回复: 这个总结好

    2019-05-13
    10
  • Adolph
    为什么要四次挥手
    任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。

    举个例子:A 和 B 打电话,通话即将结束后,A 说“我没啥要说的了”,B回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”,A 回答“知道了”,这样通话才算结束。

    作者回复: 是的

    2019-03-27
    10
  • hquery
    敲黑板,这是面试重点
    2018-07-24
    10
  • HunterYuan
    老师回答,@正是那朵玫瑰的第一个问题,感觉稍微有点问题,我理解,不是每次数据交互的会发ack,有些ack是可以合并的,用于减少数据包量,通过wirshark抓包,也证实了。理由是,因为ack号是表示已收到的数据量,也就是说,它是告诉发送方目前已接收的数据的最后一个位置在哪里,因此当需要连续发送ack时,只要发送最后一个ack号就可以了,中间的可以全部省略。同样的机制还有ack号通知和窗口更新通知合并。这是我的理解,若有问题,希望老师多多指教。谢谢
    2018-07-14
    8
  • babos
    四次挥手是不是可以做成三次,把第二步和第三步的ACK和FIN一起发

    ———————
    因为b可能还有一些事情没做完,需要做完了才能结束
    2018-07-02
    1
    8
  • 正是那朵玫瑰
    老师有几个疑问:
    1、当三次握手建立连接后,每次数据交互都还会ack吗?比如建立连接后,客户端发送数据包给服务器端,服务器成功收到数据包后会发送ack给客户端么?
    2、如果建立连接后,客户端和服务器端没有任何数据交互,双方也不主动关闭连接,理论上这个连接会一直存在么?
    3、2基础上,如果连接一直会在,双方又没有任何数据交互,若一方突然跑路了,另一方怎么知道对方已经不在了呢?在java scoket编程中,我开发客户端与服务器端代码,双方建立连接后,不发送任何数据,当我强制关闭一端时,另一端会收到一个强制关闭异常,这是如何知道对方已经强制关闭了呢?

    作者回复: 是的,每次都ack。可以有keepalive,如果不交互,两边都不像释放,那就数据结构一直占用内存,对网络没啥影响。必须是发送数据的时候,才知道跑路的事情。你所谓的强制关是怎么关?有可能还是发送了fin的

    2018-06-12
    7
  • 姜戈
    Tcp三次握手设计被恶意利用 ,造就了ddos。

    作者回复: 是有连接攻击的

    2018-06-11
    7
  • William
    感谢老师耐心回答,另外RFC文档上,microsecond是微秒哈,毫秒是milisecond😁

    作者回复: 哦,谢谢指正

    2018-11-23
    5
收起评论
99+
返回
顶部