趣谈网络协议听课笔记

TCP/UDP处于运输层

网络协议层

UDP

UDP报文

UDP报文比较简单:主要包含有源端口号和目的端口号。从而也看出UDP简单粗暴,只要有了目的端口号,就可以随意发送。
UDP有以下几个特点:

  1. 沟通简单,协议简单,无需关注太多细节,默认网络是相同的并且可达的;
  2. 信任对方,无需建立连接,可以随意的往任意端口传输数据,也可以监听该端口,无论谁都可以往该端口传输数据
  3. 不会对网络环境做出改变,无论网络环境多恶劣,你叫我发我就发。
UDP与TCP的区别:

TCP是面向连接的,即在相互通信之前,会进行3次握手,建立连接。所谓的建立连接,是为了在客户端和服务端维护连接,而建立一定的数据结构来维护双方交互的状态,用这样的数据结构来保证所谓的面向连接的特性。
UDP是无连接的。

  1. TCP提供可靠交付,IP是不提供可靠交付的,通过TCP连接传输的数据,有序、无差错、不丢失。UDP则继承了IP的特性,不保证交付,不保证丢失,不保证按序到达。
  2. TCP是面向字节流的,发送的时候没头没尾,流可以分成一个个IP包进行发送,接收端可以按照TCP中的序号对数据进行排序,然后累计,一次性向上交付。UDP继承了IP的特性,基于数据包的,一个一个IP包的发送,接收端接收到一个向上交付一个。
  3. TCP是有拥塞控制的,如果意识到网络环境不好了,会主动降低发送速率。UDP则不关心网络环境,只要上层叫我发数据,我就发。
  4. TCP是一个有状态服务,发送端清除的记录着那些包发送了,哪些包没法送,哪些包确认了,应该从哪开始发等信息。UDP则是无状态的,只要我发出去了,我就不管了。

TCP

网络天然是恶劣的,丢包、乱序、重传、拥塞是常有的是,TCP的提出就是要解决这些问题的,用来解决在不可靠的信道上面进行可靠的传输。

如何确定一个TCP连接:五元组,(协议、本机ip、本机端口、远程主机ip、远程主机端口)

TCP报文

首先,源端口号和目的端口号是必须的,这2个参数和源IP、目标IP的组合将决定该数据要提交给哪个应用。
序号(32位):序号的存在是用来解决乱序的问题,有了序号,即使数据包到达接收端是乱序的,接收端依然可以重新组成有序报文。
确认序号(32位):确认序号的存在是用来解决重传问题,接收方在接收到报文后如果不通知发送方我已经接收到该报文,发送方怎么知道接收方收到没,自己需不需要重传。
状态位:引起连接状态的变更。SYN,同步序号标志位;ACK,确认序号标志位;RST,重置连接标志位;FIN,释放连接标志位。
窗口:窗口的存在是用来做流量控制,发送方通过该值通知对方自己所能处理的窗口大小,从而控制对方发送数据的速率。
校验和:奇偶校验,用来检验TCP报文段在传输过程中是否出错。

TCP3次握手的原因
  1. 3次握手可以看做是双方的单向通讯,A向B发起连接请求,并受到B的应答请求,对于A来说,它的消息是有去有回的,因此认为连接建立了;B在发送应答之后,也在等A的应答之应答,只有收到该应答之应答,对于B来说,消息才是有去有回的,才能认为连接是建立的;
  2. 避免网络上无效的连接请求,如果A的连接请求重发了多次,A和B再重发的请求下面完成了一次连接,此时之前的请求报文又到了B,B无法知道这个是不是之前已经发起的连接请求,会再发送应答给A,此时由于A压根没有发起请求,忽略该应答。由于B很久没有收到A的应答之应答报文,于是关闭该连接,该连接不成立。
  3. 确认双发的数据包序号,双发每次在新的连接的序号都不是从1开始的,而是随着时间的变化而变化的,这样的做法是防止与旧连接的数据产生冲突。这个序号的起始序号是随着时间变化的,可以看成一个 32 位的计数器,每4ms加一,如果计算一下,如果到重复,需要4个多小时,旧连接的数据早就由于TTL到达而被丢弃了,因此不会产生序号冲突的问题。
TCP4次挥手的原因

FIN报文只能关闭一方的连接,而另一方连接是否关闭需要由对方决定,而每一次FIN报文都需要一个ACK报文确定,因此总共需要4次交互。

TCP状态流转图

在这个图中,加黑加粗的部分,是上面说到的主要流程,其中阿拉伯数字的序号,是连接过程中的顺序,而大写中文数字的序号,是连接断开过程中的顺序。加粗的实线是客户端 A 的状态变迁,加粗的虚线是服务端 B 的状态变迁。

上面可以看到A在FIN-WAIT-2收到B的FIN报文会进入TIME-WAIT状态,这个状态会持续一段时间,通常设置为2MSL,MSL表示Maximum Segment Lifetime,即报文最大生存时间,也就是数据包在网络上存在的最长时间,超过这个时间的报文会被网络丢弃。实际应用中常用的是30秒,1分钟和2分钟等。需要等候一段时间的原因有2个:

  1. 保证TCP的连接能够正常的关闭:如果A再发送ACK之后直接进入CLOSED状态,如果B再等待一段时间后没有收到该ACK报文,就会重新发送FIN报文,此时由于A已经进入CLOSED状态,就会返回RST报文,那么对于这个TCP连接来说是异常关闭的;
  2. 保证这次发送的所有重复报文在网络中消失:如果A直接进入CLOSED状态,那么此时B在重新发起一个连接(同样的端口,不过一般这种可能性较低)那么就会生成一个新的连接;此时网络上可能存在滞后的上一个连接的数据包,这些数据包在新连接建立之后才到达A,就会造成数据的混淆。

至于为什么要等2MSL,是因为A发送ACK报文最多需要MSL到达B,B如果没有收到ACK报文,会重新发送FIN报文,又最多需要MSL到达A,那么一来一回就需要2MSL的时间。
题外话:socket的SO_REUSEADDR选项可以让处于TIME-WAIT状态的端口可以直接被使用。

TCP报文的累计确认和超时重传
累计确认

TCP是保证可靠交付的,每发出的报文都要求对方发送ACK确认报文,但如果对没收到一个包都发送一次应答,那么效率比较低。因此TCP使用了累计重传方式来提高效率,对于接收到的数据包,不是一个一个去应答,而是会应答一个ID,表示这个ID之前的包都收到了。

为了记录发送和接收的数据包,发送端和接收端会维护一个缓存。如下图:

对于发送端,会维护一个滑动窗口,滑动窗口之间的数据可以无须等待前面数据的确认即可发送。每当收到新的确认包,滑动可以往前移动。滑动只有不动和往前移动两种状态。

TCP发送端缓存

LastByteAcked:表示之前的数据包已经发送并得到了确认;
LastByteSent:表示之前的数据包已经发送;

TCP接收端缓存

MaxRcvBuffer:表示接受可以缓存的数据包;
LastByteRead:表示之前的数据包已经被应用读取;

超时重传

RTT:报文往返时间,指一个报文发出的时间,以及接收到相应的ACK确认包之间所跨越的时间,TCP通常用来计算超时重传时间。
RTO(Restransimission Time-Out):超时重传时间,发送方在规定的RTO时间内没有收到对方的确认报文,就要重传已发送的报文段。

平滑RTT:SRTT = SRTT + α (RTT - SRTT)  
加权移动平均:DevRTT = (1-β) DevRTT + β |RTT-SRTT|
RTO = μ * SRTT + ν * DevRTT
在Liunx下,α = 0.125, β = 0.25, μ = 1, ν = 4
TCP的流量控制

对于数据包的确认报文中,带有接收方能够处理的窗口大小,接收方可以通过该字段控制发送方的滑动窗口大小,甚至可以将滑动窗口的大小控制为0。当滑动窗口为0时,发送方会定时发送窗口探测报文,看看是否有机会可以调整滑动窗口的大小。

TCP的拥塞控制

拥塞控制主要来避免两种现象,包丢失和超时重传。一旦出现了这些现象就说明,发送速度太快了,要慢一点。

拥塞控制也是通过窗口的大小来控制的,前面的滑动窗口rwnd是怕把接收端的缓存填满,拥塞控制cwnd的窗口是怕把网络填满。因此,最终的wnd的大小是这么决定的:wnd = min(cwnd, rwnd)
cwnd窗口大小控制如下:

慢启动

TCP开始传输数据时,cwnd设置为一个报文段,一次只能发送一个,即cwnd=1;当收到这个报文段的ACK时,cwnd+1变为2,一次能够发送两个;当收到这两个报文段的ACK,每个确认ACK会导致cwnd+1,两个报文段会使cwnd+2变为4,一次能够发送四个;当收到这个四个报文段的ACK,cwnd+4变为8,以此类推,可以看出,这是一个指数增长的过程。这就是慢启动算法。

拥塞避免

当然,这个不能一直无限的按指数增长下去,会有个慢启动门限(ssthresh,通常为65535个字节),当超过这个门限值,每收到一个报文段的ACK,cwnd就增加1/cwnd,比如一次可以发送8个字节,当收到这个8个字节的ACK时,cwnd=cwnd+1/88=9,于是一次可以发送9个报文段,可以看出,当超过ssthresh之后,变成了线性增加*,这样就可以避免增长过快导致网络拥塞。
在增长到一定阶段时,只要网络出现拥塞(根据触发了RTO重传),此时将ssthresh设置为cwnd/2,将cwnd设置为1,重新开始慢启动算法。

快重传和快恢复

上面的拥塞控制只要遇到RTO重传就回到慢启动算法,未免太过激进。并且RTO的时间也比较长。TCP中有一个快重传的方法,当接收端收到一个中间序号报文(即前面有部分序号报文没有收到),就立马发送发送冗余的ACK报文,那么接收端在接收到连续的3个ACK报文之后,就可以立即重传丢失的报文,无需等待RTO到期。这就是快重传算法
快恢复是在快重传的基础之上的,在发送端收到3个连续的ACK报文时,认为网络环境并没有那么糟糕(毕竟还是有数据包到达对面的),没必要采取过激的算法(直接重新开始慢启动),而是将ssthresh设置为原来的一半(cwnd/2),cwnd设置为ssthresh+3,然后开始拥塞避免算法。

TCP拥塞控制

TCP拥塞控制有以下问题:

  1. 丢包并不代表着通道满了,也可能是管子本来就漏水。例如公网上带宽不满也会丢包,这个时候就认为拥塞了,退缩了,其实是不对的。
  2. TCP 的拥塞控制要等到将中间设备都填充满了,才发生丢包,从而降低速度,这时候已经晚了。其实 TCP 只要填满管道就可以了,不应该接着填,直到连缓存也填满。

进阶:见Google提出的BBR算法。

DNS

Domain Name System,域名系统,用来将域名转化为IP地址,域名系统一定是高可用、高并发、分布式的。

根域名服务器:返回顶级域名服务器的IP地址;
顶级域名服务器:返回权威域名服务器的IP地址;
权威域名服务器:返回相应的主机IP。

DNS的解析流程(访问www.163.com为例):

  1. 电脑客户端会优先访问本地/etc/hosts文件,如果存在配置的IP地址,则直接返回;没有则在本地DNS缓存查看是否存在IP,如果能够找到,则直接返回;否则电脑客户端会发出一个DNS请求,首先发给本地DNS服务器,本地DNS服务器是由网络服务商提供;
  2. 本地DNS服务器收到来自客户端的请求,本地DNS首先在本地缓存表中查看是否存在对应的IP地址,如果有,则返回IP地址;如果没有,本地DNS服务器会去它的根域名服务器,“能够告诉我www.163.com的地址吗”,根域名服务器是最高层次,全球共有13套,它不直接用于域名解析,但是可以告诉本地DNS服务器去哪查
  3. 根域名服务器收到来自本地DNS服务器的请求,发现后缀是.com,指明这个域名是由.com顶级域名服务器管理,于是告诉本地DNS服务器去顶级服务器查;
  4. 顶级域名服务器:顶级就是.com.org这些一级域名,它负责管理二级域名,比如163.com,所以它可以告诉本地DNS去哪里查询;
  5. 顶级域名服务器收到来自本地DNS的请求,告诉本地DNS负责管理www.163.com的权威DNS服务器的地址;
  6. 本地DNS服务器转而向权威DNS服务器询问IP;
  7. 权威DNS服务器将对应的IP地址告诉本地DNS服务器;
  8. 本地DNS服务器再将IP返回客户端,客户端与目标建立连接。

HTTPDNS

传统DNS域名解析存在的问题:

  1. 域名缓存问题:缓存会存在过期问题,再者,上一次请求获得的IP地址在该次的情况下请求不一定是最优的;
  2. 域名转发问题:DNS解析的请求返回的IP地址可能是跨运营商,这样会导致每次访问机器慢;
  3. 出口NAT问题:出口NAT会将原来的IP地址替换掉,那么权威域名服务器无法通过源端IP地址提供最优的解析结果;
  4. 域名更新问题:如果IP对应的IP更新了的话,在全网生效需要一定的时间,那么此时部分用户可能会访问错误的IP地址;
  5. 解析延迟问题:DNS的查询需要经过多次的DNS递归查询才能获得最终的解析结果,这回带来一定的延时。

为了解决上述问题,HTTPDNS应运而生。HTTPNDS不走传统的DNS解析,而是自己搭建基于HTTP协议的DNS服务器集群,分布在多个地点和多个运营商。当客户端需要DNS解析的时候,直接通过HTTP协议进行请求这个服务器集群,得到就近的地址。

工作模式:当手机应用要访问一个地址的时候,首先看是否有本地的缓存,如果有就直接返回。这个缓存和本地 DNS 的缓存不一样的是,这个是手机应用自己做的,而非整个运营商统一做的。如何更新、何时更新,手机应用的客户端可以和服务器协调来做这件事情。
如果本地没有,就需要请求 HTTPDNS 的服务器,在本地 HTTPDNS 服务器的 IP 列表中,选择一个发出 HTTP 的请求,会返回一个要访问的网站的 IP 列表。
手机客户端自然知道手机在哪个运营商、哪个地址。由于是直接的 HTTP 通信,HTTPDNS 服务器能够准确知道这些信息,因而可以做精准的全局负载均衡。

请求示例:

curl http://106.2.xxx.xxx/d?dn=c.m.163.com
{"dns":[{"host":"c.m.163.com","ips":["223.252.199.12"],"ttl":300,"http2":0}],"client":{"ip":"106.2.81.50","line":269692944}}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 1、TCP为什么需要3次握手,4次断开? “三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端...
    杰伦哎呦哎呦阅读 3,439评论 0 6
  • 传输层提供的服务 传输层的功能 从通信和信息处理的角度看 ,传输层向它上面的应用层提供通信服务,它属于面向通信部分...
    CodeKing2017阅读 3,503评论 1 9
  • 1.这篇文章不是本人原创的,只是个人为了对这部分知识做一个整理和系统的输出而编辑成的,在此郑重地向本文所引用文章的...
    SOMCENT阅读 12,979评论 6 174
  • 运输层协议概述 从通信和信息处理的角度看,运输层向它上面的应用层提供通信服务,它属于面向通信部分的最高层,同时也是...
    srtianxia阅读 2,322评论 0 2
  • 博主最近在复习HTTP,之前用书主要是《计算机网络》谢希仁版本,最近结合网上博客,进行复习和提纲式的总结。 一、概...
    stoneyang94阅读 4,124评论 1 8