计算机网络-自顶向下
计算机网络中的协议
[TOC]
1.应用层协议
🚀🎈🏆💬👍❤️💪😂👌😑😓⚡👴🏻⭐❓🥳❗️✔️❌🙏
定义了运行在不同端系统上的应用程序进程如何相互传递报文。位于应用层的信息分组称为报文。
各层的所有协议被称为协议栈。
应用层协议定义了:
1.1 HTTP协议⭐
HTTP协议是基于TCP/IP协议之上的应用层协议。HTTP默认端口号为80。它也可以承载在TLS和SSL之上,通过加密、认证的方式实现数据传输的安全,称为HTTPS,HTTPS默认端口号为443。
1.1.1 工作原理
当客户端输入一个URL后,HTTP协议就开始运作了。HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文。服务器以一个响应报文作为响应。
1.1.2 请求报文格式
请求行和首部行编码为ASCII码。请求体根据header中的Content-Type规定body里采用什么编码。
1.1.2.1 请求行(request line)
字段:请求方法 URI 协议
①GET: GET /books/?sex=man&name=Professional HTTP/1.1 或 GET /index.html HTTP/1.1
用来获取/查询资源,请求访问指定服务器上的资源。直接在浏览器中键入网址搜索的方式,其请求方法就是GET,当浏览器请求一个对象时,在URL字段中会包含这个对象的标志,即GET请求的数据信息都在URL中,比如这个URI,books是访问服务器资源的路径,sex=man&name=Professional 是请求参数信息,即浏览器要访问的对象。这就是GET方法的一个缺点,请求参数全部暴露在URL中,不安全。而且URL长度有限,无法包含许多请求参数。
②POST: POST /books/some HTTP/1.1
用来提交表单。在form表单中,可以主动选择method为POST(当然也可以指定为GET),一般POST不用来获取资源,而是向服务器提交/上传资源,比如提交用户数据验证登录用户、上传文件之类的。一般这些请求参数都放到请求体中。
③HEAD:HEAD /index.html HTTP/1.1
获得报文首部。和GET方法一样,只是HEAD只返回首部,即响应报文仅包含首部信息,HEAD一般是开发者用来进行调试跟踪,用于确认 URI 的有效性及资源更新的日期时间。
④PUT:PUT /books/some HTTP/1.1
用于上传对象到指定的Web服务器上的指定路径。
感觉和POST有点相似,百度查了一下,发现POST不具有幂等性,而PUT具有幂等性。所谓幂等性,即对同一URL的一次和多次请求某一个资源应该具有同样的副作用(指的是同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的)。当服务器上没有这个对象时,就创建这个对象,而当服务器上已经有这个对象时,就不会再次创建了,而是更新这个对象,所以在服务器上这个对象是唯一的。而非幂等性就是提交几次请求,就在服务器上创建几个相同的对象。
但是会产生安全问题,因为 HTTP/1.1 的 PUT 方法自身不带验证机制,任何人都可以上传文件。而POST方法,当请求的资源被加密(就拿登录一个淘宝网页来说),服务器会返回401响应,浏览器会弹出一个对话框,要求浏览器提交用户名、密码,用户在输入身份验证信息后提交到服务器,服务器验证成功后用户才可以进入他自己账号下的淘宝。
⑤DELETE:用于删除指定服务器上的指定路径的资源,但由于HTTP1.1对于这个方法也不具有验证机制,任何人都可以删除服务器上的内容,因此此方法也被视为是不安全的,一般很少用。
1.1.2.2 首部行(header line)
①HOST:www.baicu.com
表示请求对象所在的主机(在web高速缓存中有用)
②Connection:close
通知浏览器不使用持续连接,而是一个请求发送完之后就关闭这条连接。
补充:持续连接:HTTP中默认是持续连接,即Connection:keep-alive,服务器在发送完响应后保持该TCP的连接,在相同的客户和服务器之间,后序的请求和响应报文能通过相同的连接进行传送。 但如果一条连接一定时间没有使用就会自动断开。
③User-agent:Mozilla/5.0
用户代理(即浏览器的类型)。
④Accept:text/html,application/xhtml+xml,image/webp
客户端可支持的数据类型(Content-Type),以MIME类型来表示。
⑤Accept-Language:zh-CN;en-US
客户端可以支持的语言。
⑥Accept-Encoding:gzip,deflate
客户端支持的服务器对响应数据的编码格式。
⑦Content-Type:application/x-www-form-urlencoded
指定请求体的数据编码方式。
application/x-www-form-urlencoded是form表单的默认编码方式,提交的数据按照 key1=val1&key2=val2 的方式进行编码,并放到请求体中。
⑧Content-Length:43
请求体的长度。
⑨Origin :https://baidu.com
用于指明当前请求来自于哪个站点。
⑩Cookie:JSESSIONID=7BDD60BE24561687329E8DF0C63B0D
因为 HTTP 是无状态的连接,当会话结束后,在下一次会话中,服务器并不知道和上一次的是否是同一个用户,而且也并不会自动维护用户的上下文。所以当浏览器第一次请求这个服务器时,为了识别用户,服务端给每个第一次登录的用户生成一个唯一标识(session_id)和session,每一个 session_id 和一个session 值绑定在一起,这个值是用户信息加密后的字符串。第一次创建 session 的时候,服务端会在 HTTP 响应中告诉客户端 session_id 并存储在 cookie 字段中,浏览器会提取出这个值,然后以key:value的形式将这个值存储在本地,浏览器后续每次针对该网站的所有请求都会加上这个 session_id,每次服务端收到请求后,就能根据这个 session_id 来确定用户是谁,从而就可以将多次请求转发到同一个Web服务器上。
服务器生成一个session,并且将它保存在服务器上。Session对象存储特定用户会话所需的属性及配置信息。
cookie的有效期:看浏览器的设置吧,大概也就是一个月左右。session的有效期:对于用户来说,session的有效期是在浏览器从打开到关闭,对于服务器来说,默认是30分钟session自动销毁,但可以设置。
Cookie 一般用来保存用户信息。Session 的主要作用就是通过服务端记录用户的状态。
⑪If-Modified-Since:Web,9 Sep 2015 09:23:24
缓存的数据的有效时间,即它还没有更新。
这个是代理缓存服务器向真正的Web服务器发送的查询请求的首部行中有的。首先浏览器向代理服务器发送请求,代理服务器向Web服务器查询 存到代理服务器中的请求对象是否被改变,这个字段的内容是上次修改的时间。
1.1.2.3 请求体(entity body)
(data…data..data…data…)
GET方法没有请求体,其请求参数都在URL中,POST的请求参数在请求体中。
1.1.3 响应报文格式
1.1.3.1 状态行(status line)
字段:协议 状态码 HTTP/1.1 200
状态码:
200 OK:请求成功,信息在返回的响应报文中。
301 Moved Permanently :请求的对象已经被永久转移了,新的URL定义在响应报文的Location首部行中,客户软件将自动获取新的URL。
400 Bad Request:一个通用的差错代码,指示该请求不能被服务器理解。
404 Not Found:被请求的文档不在服务器上。
505 HTTP Version Not Supported:服务器不支持请求报文使用的HTTP协议版本。
1.1.3.2 首部行(header line)
①Last-Modified:数据的最后更新时间
一般是Web服务器为了响应代理缓存器而生成的首部行
②Connection:close
首部行告诉客户,发完这个HTTP响应就关闭这个tcp连接
还有一个情况就是 Connection:keep-alive
keep-alive:timeout=20
③:Content-Encoding:gzip
内容编码:服务器在发送响应报文时,可以对响应体进行编码,这样减少了传输的资源大小,加快了传输速率,并且也相当于对数据进行了加密。
编码格式 | 描述 |
---|---|
gzip | 表明实体采用 GNU zip 编码 |
compress | 表明实体采用 Unix 的文件压缩程序 |
deflate | 表明实体采用 zlib 的格式压缩 |
identity | 表明没有对实体进行编码。当没有 Content-Encoding 首部是,就默认为这种情况 |
④Content-Length:40
如果消息体进行了内容编码,Content-Length 首部说明的就是编码后(encoded)的body的字节长度,而不是未编码的原始主体长度。字节数。。这个字段的好处:知道报文什么时候全部到达。
⑤Transfer-Encoding:chunked
在HTTP/1.1中只有这一个值,表示分块传输。
chunked编码使用若干个chunk串连而成,由一个标明长度为0的chunk标示结束。一个chunk块由头部和正文两部分组成,头部存的是这个块中正文部分(数据)的长度,CRLF,正文部分,CRLF。最后一个0的块的头部是0,CLRF,正文部分没有数据,CRLF。
Transfer-Encoding和Content-Length是不会同时出现的。Content-Length如果服务器端计算出错的话(因为报文长度经常是不可预测),假设Content-Length小于响应体的总长度,则传输会被截断,如果大于,则无法判定当前响应已经结束,会将请求持续挂起。为了解决这一问题,产生了Transfer-Encoding
⑥Server:Apache/2.2.3
表明该报文是由一台Apache Web服务器产生的
⑦Last-Modified:表明对象创建或最后修改的时间和日期
⑧Content-Type:text/html
说明实体体中的数据类型,以MIME规格定义的数据类型来表示。
⑨Date:Tue,18 Aug 2015 15:44:04 GMT
表明服务器产生并发送这个响应报文的日期和时间。
1.1.3.3 响应体(entity body)
(data…data..data…data…)
1.1.4 历史版本
1.1.4.1 HTTP/1.0
HTTP 1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接。即默认使用短连接。非持续连接
1.1.4.2 HTTP/1.1
1.长连接:HTTP 1.1支持持久连接(HTTP/1.1的默认模式使用持续连接Connection:keep-alive),在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。
HTTP/1.1的持续连接有非流水线方式和流水线方式 。流水线方式是客户在收到HTTP的响应报文之前就能接着发送新的请求报文。与之相对应的非流水线方式是客户在收到前一个响应后才能发送下一个请求。 —-javaguide
但是流水线方式,虽然客户端可以在没有接受到服务器的响应报文就发送下一个请求报文,但是在服务器端要求必须按照请求发送的顺序返回响应,当顺序请求多个文件时,其中一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,这就是队头阻塞 。
若timeout时间内没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔一定时间发送一次。若一连发送 10 个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,接着就关闭这个连接。—-谢希仁
2.Host请求头字段:(必须有)有时候一个服务器主机提供多个服务,比如假设www.baidu.com、 www.taobao.com 、www.jd.cm它们的服务器是同一个,那么这些域名对应的IP地址肯定是相同的,那我访问百度的网页,服务器怎么知道我访问的是百度呢?就通过host字段来区分。如果我们不传这个字段还会报一个400(bad request)的状态码
3.新增了一些请求方法:OPTIONS、PUT、DELETE、TRACE、CONNECT (也新增了一些头字段)
4.新增了错误通知的状态码:在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
5.缓存处理:在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
1.1.4.3 HTTP/2.0
1.二进制分帧:HTTP/1.x都是基于文本的,而HTTP/2.0是基于二进制六的。2.0引入了 帧(frame)和流(stream)。在应用层(HTTP)和传输层(TCP)之间增加一个二进制分帧层。http/2.0把HTTP消息分解为更小的独立的帧,然后可以交错着通过一个tcp连接发送给服务器,在服务器端通过帧中的标识,重新把帧还原为HTTP请求报文。
2.多路复用:由于HTTP/1.1的长连接会产生队头阻塞,因此发明了多路复用机制。就是交错发送。
下面是采用流水线方式的长连接和多路复用的区别。
3.头部数据压缩:
在HTTP1.1中,HTTP请求和响应都是由请求行、首部行、请求体三部分组成。一般而言,请求体都会经过gzip压缩(根据首部行的Content-Encoding),或者本身传输的就是压缩过后的二进制文件,但状态行和头部却没有经过任何压缩,直接以纯文本传输。随着Web功能越来越复杂,每个页面产生的请求数也越来越多,导致消耗在头部的流量越来越多,尤其是每次都要传输UserAgent、Cookie这类不会频繁变动的内容,完全是一种浪费。
在HTTP2.0中,我们使用了HPACK(HTTP2头部压缩算法)压缩格式对传输的header进行编码,减少了header的大小。并在两端维护了索引表,用于记录出现过的header,后面在传输过程中就可以传输已经记录过的header的键名,对端收到数据后就可以通过键名找到对应的值。
4.服务器推送(server push):
推送技术是指通过客户端与服务器端建立长链接,客户端可以接收由服务器端不定时发送的消息。服务端根据客户端的请求,提前返回多个响应,推送额外的资源给客户端。(服务器向额外推送的话,会发送一个PUSH_PROMISE帧,帧中包含预推送资源的首部,如果客户端响应,说明它需要这个资源,服务器则会发送一个Data帧,包含推送的数据)。
1.1.4.4 HTTPS
——-留坑——-看到https再填——–
1.2 SMTP协议
使用TCP可靠传输服务。代理1对应的服务器1所在端口是25,代理2对应的服务器所在的端口是110
工作原理:用户代理1客户端向用户代理2客户端发送邮件,首先代理1会通过SMTP协议将邮件(其中携带着目的地的邮箱地址,即用户代理2对应的服务器)push给代理1对应的邮件服务器1,然后服务器1将邮件通过SMTP协议发送给代理2的邮件服务器,代理2通过POP3或IMAP协议从服务器2中pull邮件。
SMTP协议与HTTP协议的区别:
- SMTP是一个推协议,即将数据推给接收方。HTTP是一个拉协议,从接收方获取数据。
- SMTP的报文必须是按照标准ASCII码编码,而HTTP报文的实体体不需要用ASCII码编码,而是根据首部行的Content-Type来编码。
- SMTP将所有报文对象放在一个报文中,HTTP则是一个对象封装一个报文。
1.3 DNS协议
DNS请求和响应报文使用UDP数据报经过端口53发送。
1.3.1 DNS层次结构
1.3.1.1 根DNS服务器
根域:.
根域名服务器中有一个根域名列表,里面记载着顶级域名和对应的TLD服务器的IP地址)。
1.3.1.2 TLD(DNS)服务器
顶级域比如:com、cn、net、edu等等
TLD服务器管理着注册在该顶级域下的所有二级域的权威DNS服务器的IP地址,即它提供了权威DNS服务器的IP地址。
1.3.1.3 权威DNS服务器
二级域比如:baidu.com、taobao.com、zzu.edu
权威DNS服务器管理着注册在该二级域下的所有三级/四级域的主机的IP地址。三/四级域有www.baidu.com、www.taobao.com、gaia.cs.umass.edu 权威服务器下记录着主机的IP地址
1.3.1.4 本地DNS服务器(不在DNS层次结构中)
这个DNS服务器地址是通过在主机的这个位置设置的,常见的有电信、联通、谷歌、阿里等的本地 DNS 服务。当hosts文件中没有对应IP地址时,网络应用程序调用解析器(一段程序),解析器生成dns查询报文,通过协议栈将报文发送出去,这时发送的目的地就是主机上配置的dns服务器的地址。
自动获得DNS服务器地址:
这里分两种情况。1.你的电脑是直连运营商网络,即手机是4G网,电脑连接着手机的热点。这时候本地DNS服务器就是通过DHCP(系统)分配到的运营商的DNS服务器。2.你的电脑连接的是家里的WiFi,即通过路由器上网,这时候电脑如果想上网,需要先通过路由器,那么所有的DNS查询报文都会先经过路由器,然后再通过路由器向上层转发DNS报文。并且路由器执行DHCP服务,所以路由器就将它自己的IP地址分配给了主机的本地DNS服务器的IP地址。
1.3.2 DNS记录和报文和缓存
1.3.2.1 资源记录(RR)
所有DNS服务器寻出了资源记录,这些记录提供了主机名到IP地址的映射。资源记录是一个包含了下列字段的4元组: (Name,Value,Type,TTL),其中TTL是资源记录应当从缓存中删除的时间(资源记录的生存时间)。
Type | Name | Value |
---|---|---|
A | 主机名(如www.baidu.com) | 该主机名对应的IP地址(202.108.22.5) |
NS | 域(如com) | 权威DNS服务器的主机名(它知道如何获取该域中主机IP地址)(如baidu.com) |
CHAME | 主机别名(如foo.com) | 规范主机名(relay1.bar.foo.com) |
MX | 邮件服务器别名(如foo.com) | 规范主机名(mail.bar.foo.com) |
获取除了邮件服务器以外的服务器主机的别名,DNS客户应该请求一条CHAME记录。
对于Type=NS,如果这个DNS服务器上有一条这样的记录,那必定也有一条A记录,该记录提供了再NS记录的Value字段中的权威DNS服务器的IP地址。比如,本地DNS服务器向根DNS服务器发送一个查询报文,查询gaia.cs.umass.edu的IP地址,但是根DNS服务器中没有该主机名的一条A记录,但是它有一条NS记录,(umass.edu,dns.umass.edu,NS),即umass.edu域的权威DNS服务器的主机名是dns.umass.edu。然后还有一条A记录,(dns.umass.edu,192.168.167.91,A), 即根DNS服务器指定 则本地DNS服务器去dns.umass.edu服务器中查到了umass.edu域的IP地址,再接着去umass.edu域DNS服务器查询是否有主机的记录。
其实也可能dns.umass.edu中没有gaia.cs.umass.edu的IP地址,但是它有一条NS记录:(cs.umass.edu,dns.cs.umass.edu,NS),然后还有一条A记录,(dns.cs.umass.edu,192.168.167.91,A),即它知道cs.umass.edu域的权威服务器dns.cs.umass.edu的IP地址,它觉得dns.cs.umass.edu可能知道gaia.cs.umass.edu的IP地址。然后本地DNS服务器再向dns.cs.umass.edu查询,最终找到了一条包含主机名的A记录。
———————摘自 《自顶向下》。因为感觉对这个查询过程有点迷,就摘了两段理解了一下。
1.3.2.2 报文格式
1.3.2.3 DNS缓存
首先是本地:操作系统缓存:操作系统的缓存其实是用户自己配置的 hosts 文件。比如 Windows10 下的 hosts 文件存放在 C:\Windows\System32\drivers\etc\hosts
本地DNS服务器可以将之前收到的主机名到IP地址的映射缓存到它的本地存储器中,这样下次如果请求相同主机名的IP地址就直接查缓存就行了,缓存没有再进行迭代查询。
由于主机名和IP地址之间的映射不是永久的,所以DNS服务器在一段时间就将丢弃缓存的信息。
1.3.3 查询方式
递归查询和迭代查询。
区别:从请求主机到本地DNS服务器的查询是递归的,其余的查询是迭代的。
可以从算法上面理解,做递归题时,⭐你永远要明白这个方法的作用并且相信它能完成这个任务⭐,所以你在第一层,向得到后面层的结果,就直接调用这个方法,相信它一定给你预期的完成结果,然后你仅仅拿到返回值之后再进行return或者什么操作就行了。对于DNS查询也是这样,第一层是请求主机去问本地DNS服务器,请求主机不管本地DNS服务器怎么操作,请求主机就相信本地DNS服务器一定能交给它那个IP地址,请求主机很省心。
对于迭代,就是需要自己通过一遍遍的运算,一步步找结果。即本地DNS服务器一个一个的去查IP地址,先查根DNS服务器,查到一个相关的结果,再去另一个地方查。
1.3.4 负载均衡
当一个Web站点有冗余web服务器时(即同一个域名对应多个IP地址,这样做的目的是减小一个web服务器的访问负担),此时如果一个主机请求该站点的IP地址,DNS服务器会返回这个IP地址集合,但在每次的响应中循环这些地址的次序(轮询),因为客户端总是向IP地址排在最前面的服务器发送http请求报文。
但是轮询是有缺点的,如果某一个服务器出现故障,DNS服务器可不知道,会按照原样返回一定顺序的IP地址集合。所以这时候加入了负载均衡器,将该站点域名映射到负载均衡器上,DNS服务器只返回负载均衡器的IP地址,由负载均衡器来判断应该转发请求到哪个Web服务器上。
1.3.5 DNS污染
DNS污染:是一种让一般用户由于得到虚假目标主机IP而不能与其通信的方法。由于通常的DNS查询没有任何认证机制,而且DNS查询通常基于的UDP是无连接不可靠的协议,因此DNS的查询非常容易被篡改,通过对UDP端口53上的DNS查询进行入侵检测,国内的服务器(非DNS)监控到用户访问的已经被标记地址时,则立即伪装成目标域名的DNS服务器给查询者返回虚假错误的IP地址。用户所访问的DNS服务器也会发送正确的数据包,但是由于虚假的IP数据包先到达主机,操作系统就会认为第一个是正确的,从而忽略后面的数据包。
然后用户的本地DNS服务器上就有了一条这个域名与虚假IP地址的映射记录,在记录的有效期内,每次用户再访问这个站点时,本地DNS服务器就会将虚假的IP地址返回。
DNS劫持:通过劫持了DNS服务器,通过某些手段取得某域名的解析记录控制权,进而修改此域名的解析结果,导致对该域名的访问由原IP地址转入到修改后的指定IP,其结果就是对特定的网址不能访问或访问的是假网址,从而实现窃取资料或者破坏原有正常服务的目的。DNS劫持通过篡改DNS服务器上的数据返回给用户一个错误的查询结果来实现的。这个解决方法是吧系统DNS的IP地址换成国外的DNS服务器的IP地址。
2.运输层协议
运输层协议为运行在不同主机进程之间提供了逻辑通信。
在发送端,运输层将从发送应用进程程序接收到的报文段转换成运输层分组,这个分组称为(运输层)报文段。🚀🎈🏆💬👍❤️💪😂👌😑😓⚡👴🏻
——有个问题?我看书上说当生成一个套接字时,就为他分配一个端口号这样的标志符。然后每个tcp头部封装的目的主机端口号其实是套接字的端口号。但是不是说进程有唯一的端口号吗,为什么套接字中目的进程端口号不是进程的端口号,而是目的套接字的端口号?而且多路复用和多路分解也是从套接字中收集报文和将所有报文定向发送进对应进程的对应的套接字中,然后进程再去套接字中取。难道进程套接字的端口号就是进程的端口号?
2.1 UDP协议
2.1.1 UDP报文段格式
源端口号和目的端口号都是16bit,所以端口号的可取范围是065535。周知端口号范围是01023,他们是保留给周知应用层协议使用的,不能被随意使用。
检验和:发送方的UDP对报文段中所有16bit的和进行反码运算,其实就是源端口号,目的端口号,长度三者相加,如果最高位溢出的话,把溢出的1加到第一位上,得到的结果放在检验和字段中。在接收方,将源端口号,目的端口号,长度,检验和四者相加,如果结果全为1则没有出错。
UDP既然不提供可靠传输,为什么还要提供检验和?因为不能保证源和目的之间的所有链路都提供差错检验机制。不过UDP只是做了运输协议能够做的最少的工作。
2.1.2 使用UDP的原因
- 分组首部开销少。UDP报文段首部仅有8字节,而TCP报文段首部有20字节的首部开销。
- 两个主机进行通信时无须先建立连接。TCP在开始数据传输之前需要三次握手,而UDP不需要任何准备即可进行数据传输,所以UDP不会引入建立连接的时延。
- 无连接状态。UDP不维护连接状态,也不跟踪这些参数。TCP在端系统中维护连接状态,这个连接状态包括接收发送缓存,拥塞控制参数,序号,确认号,比较麻烦。
- 对于从应用层收到的报文,UDP立即就可以发送,而无需考虑其他因素。而TCP有拥塞控制机制,如果当从源到目的之间的多条链路都很拥塞时,TCP会减小发送的速率,所以发送时延就增加了。但是UDP这样是有缺点的,没有拥塞控制机制,会造成UDP收发方之间的高丢包率,并且会挤垮TCP发送方。UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
2.2 TCP协议🚀
参考:https://en.m.wikipedia.org/wiki/Transmission_Control_Protocol
2.2.1 TCP报文段结构
源端口号和目的端口号:16bits,指示源套接字的端口号和目的套接字的端口号。
序号seq:32bits,如果设置了SYN=1,则这个序号是初始序列号,是随机生成的。如果SYN=0,则这是当前TCP报文段中的死一个数据字节的累积序列号。
确认号ack:32bit,如果设置了ACK标志,则ack字段的值为发送方期望接收的下一个seq序号。
数据偏移字段:4bits,指示TCP首部的长度,一般是20字节,即选项字段为空。最大是60字节,此时有选项字段,占40字节。
3bits的保留未用字段,设置为0。
标志字段:9bits,在TCP连接和释放中的标志字段。
NS:ECN-nonce - concealment protection
CWR:拥塞窗口缩减标志,由发送主机设置。因为接收主机在接收方到发送方的TCP ACK报文段中设置了ECE比特,所以发送主机收到这个报文段后,通过减半拥塞窗口来对一个具有ECE拥塞指示的ACK做出反应,并且在下一个发送的报文段中对CWR比特设置为1,以确认收到了拥塞指示回显
ECE:ECN-Echo,明确拥塞通告回显比特。在报文段传输的过程中(链路拥塞),ECN 感知路由器可以在 IP 报头中设置一个标记ECN=11,而不是丢弃数据包,以表示即将发生拥塞。数据包到达接收方后,接收方将标志了拥塞指示回显ECE的TCP ACK报文段给发送方。
URG:表示 Urgent 指针字段有效,指示报文段中存在着被发送方的上层设置为紧急的数据。
ACK:表示确认字段ack中的值是有效的,即该报文段包括一个对已被接收报文段的确认。客户端发送的初始 SYN 数据包之后的所有数据包都应设置此标志。当ACK=1时,确认号字段才有效。ACK=0时,确认号无效。
PSH:推送功能。请求将缓冲的数据推送到接收应用程序。指示接收方应立即将缓冲中的数据交给上层。
RST:当接收方接收到的TCP SYN报文段,其源端口和源IP地址与目的主机上的所有套接字都不匹配,即接收到非法的TCP报文段,此时目的主机发送一个特殊重置报文段,这个TCP报文段中的RST标志位为1,指示发送主机不要再发送这个报文段了。
SYN:同步序列号。发送方和接收方的第一个数据包中的这个字段有效,表示是建立连接的报文段。
FIN:表示发送方要断开连接了,这是它的最后一个数据包。
接收窗口:16bits,用来流量控制,表明接收方希望接收的字节数。
检验和:16bits,和udp 的是一个作用。
紧急指针:16bits,该字段指向紧急数据的最后一个字节。
选择字段:320bits,可选,用于发送方和接收方协商最大的报文段长度(MSS)(三次握手阶段协商)或者用作窗口调节因子时使用。一般不用
2.2.2 TCP的连接和释放
2.2.2.1 三次握手
TCP协议栈维护着两个socket缓冲区:send buffer和recv buffer。要通过TCP连接发送出去的数据都先拷贝到send buffer,即将http消息写入TCP协议栈的缓冲区中。这个缓冲区在TCP连接成功后就会被创建。
首先,客户端的TCP向服务器端的TCP发送一个TCP SYN报文段。这个报文段没有应用层数据,但是SYN字段被标志位1(表示是建立连接的报文段),SYN=1,并且客户端会适当的随机生成一个初始序号ISN,即seq=client_isn,放在序号字段中。发给服务器。
服务器接收到该报文段后,为该TCP创建缓存和变量,(但是如果客户端不发送ACK来完成第三次握手的话,通常在1min之后,服务器将终止该半开连接并释放资源),然后向客户端发送允许连接的报文段 SYN ACK报文段。这个报文段也没有应用层数据,SYN=1,在TCP首部的确认号字段中ack=client_isn+1,服务器选择自己的初始序号seq=server_isn。
🎈ack=seq+1的原因:ack指的是期望接收到下一个字节的编号;而客户端第一次发来的SYN报文段中不携带数据,(但是要消耗一个序号),当前报文段最后一个字节的编号还是client_isn,因此当前报文段最后一个字节的编号+1即为确认号。
在收到这个报文段后,客户端也要为该TCP连接分配缓存和变量。然后向服务器发送一个已收到服务器报文段的一个确认报文段。SYN=0,seq=client_isn+1,ack=server_isn+1。这个报文段的数据字段里可以携带数据。
选择合适的ISN:TCP提供了可靠的字节流数据传输,它会为应用层的每个字节分配一个序列号,初始序号为ISN(Initial Sequence Number)的字节不是以0或1开头,而是由特定算法生成的,ISN值在[0, 2^32-1]范围内。TCP通信的两端需要交换对方的ISN来控制字节流的传输。交换ISN的过程称为TCP连接建立过程,也称为虚连接或虚电路建立过程。
通信双方都交换ISN:发送方需要将IP数据包发送给接收方,但是它们可能不是按序到达的,那么接收方需要知道发送方发送的字节序号。
🍉TCP 为什么是三次握手,而不是两次或四次?
因为信道是不可靠的,但数据传输是必须可靠的。通信双方必须在通信前达成一致的数据传输信息,保证收到的数据的连续性,防止某一段数据中途丢失,比如客户端和服务器端的初始序号双方都要知道。
如果是两次握手,假如客户端发送一个SYN报文段,但是由于网络链路的阻塞,很长一段才到达服务器端,对于客户端来说这个报文早已失效,而服务器端认为是一个新的连接请求报文,因此会同意建立连接,并为这个TCP分配资源,在一定时间内一直等待客户端发来数据,因此服务器端的资源就浪费了。三次握手只能说是一个比较优的值,三次握手后就可以保证双方获得了互相的seq,四次握手又有点浪费了,三次就可以了。
参考:TCP 为什么是三次握手,而不是两次或四次? - wuxinliulei的回答 - 知乎 https://www.zhihu.com/question/24853633/answer/63668444
2.2.2.2 四次挥手
假设客户端先关闭连接
- 客户应用进程发出一个关闭连接命令,因此客户端TCP模块箱服务器端发送一个TCP终止报文段,其中首部的标志位FIN=1。
- 服务器端收到TCP报文段后,向客户端发送一个ACK确认报文。
- 接着服务器端向客户端发送一个终止报文,其中首部的标志位FIN=1。
- 客户端收到TCP报文段后,向服务器端发送一个ACK确认报文。
在此期间本地端口不可用新连接;这可以防止在后续连接期间传送与先前连接相关联的延迟数据包时可能发生的混淆。
也可以通过 3 次握手来终止连接,此时主机 A 发送 FIN,主机 B 用 FIN & ACK 回复(两步合二为一),主机 A 用 ACK 回复。
2.2.2.3 TCP的生命周期
客户TCP套接字一开始处于CLOSED的状态。客户端的应用程序发起一个新的TCP连接(应用程序调用调用socket,创建TCP套接字,分配端口号等等),然后这些信息传递给TCP协议栈,引起向服务器发送一个SYN报文段。在发送这个报文段的过程中,客户端TCP套接字进入SYN SENT状态,等待接收来自服务器端的SYN ACK报文段。当收到SYN ACK报文段后, 向服务器发送一个ACK报文段。客户端TCP套接字进入ESTABLISHED(已建立)状态。
对于服务器端,当服务器程序启动并读取配置文件完成初始化操作后,就会进入等待连接模块,在这个模块中,协议栈调用socket创建套接字,然后调用bind,将端口号写入套接字中,然后服务器TCP套接字就进入LISTEN状态,等待来自客户端的连接请求。当收到客户端的SYN报文段后,向客户端发送一个SYN ACK报文段,服务器TCP套接字进入SYN RECEIVED状态,等待ACK报文段。当收到ACK报文段后,服务器TCP套接字进入ESTABLISHED(已建立)状态。如果ACK报文段丢失,那么客户端会重传这个报文段,最终服务器端会收到ACK报文段,并进入ESTABLISHED(已建立)状态。
这时客户端和服务器端就能发送和接收包含有效载荷数据的TCP报文段了。(PS:第三次握手的时候客户端就可以在报文段中携带数据了)
——————发送数据—————-接收数据——————发送数据————–接收数据—————-
等到某个时刻,假设客户端应用程序要关闭连接。这时客户端发送一个FIN比特被置为1的报文段,TCP客户端套接字进入FIN WAIT 1 状态,等待来自服务器的确认的TCP报文段,当客户端收到该报文段后,TCP套接字进入FIN WAIT 2 状态,并等待来自服务器的FIN比特被置为1的TCP报文段,当收到服务器的FIN报文段后,客户端向服务器端发送一个确认报文段,然后套接字进入TIME WAIT 状态。如果携带ACK标志的报文丢失,客户端会重传。当经过了TIME WAIT时间后(一般是30s或1min或2min),客户端所有有关这个TCP连接的资源都被释放。连接终止,进入CLOSED状态。
当服务器端收到带有FIN比特被置为1的TCP报文段后,服务器端将会向客户端发送一个带有确认的TCP报文段,然后服务器TCP套接字进入CLOSE WAIT 状态,然后向客户端发送一个FIN比特被置为1的TCP报文段,然后服务器TCP套接字进入LAST ACK 状态,等待客户端的确认报文段。收到该报文段后,服务器端所有有关这个TCP连接的资源都被释放。连接终止,进入CLOSED状态。
TIME WAIT问题:
为什么客户端在发送过ACK报文段后,需要等待TIME WAIT时间后才彻底释放资源?
- 为了保证客户端发送的ACK报文段能到达服务器端。假如客户端再发送完确认的TCP报文段后就关闭了连接,而该报文段在传输过程中丢失了,服务器端会触发超时重传机制,再次向客户端发送FIN比特被置为1的TCP报文段,而此时客户端已经关闭了连接,这个TCP报文段被客户端视作一个非法的TCP报文段,客户端会向服务器端发送一个RST比特被置为1的TCP报文段,表示拒绝此次通信,以后也不要给他发送这个报文段。那么服务器就不能按正常步骤进入CLOSED状态。那么就会耗费服务器的资源。当网络中存在大量的LAST ACK状态,服务器最终会崩溃。
- 在第四次挥手后,经过TIME WAIT时间足以让在本次连接中产生的报文段都消失,而不会影响下一次的TCP连接。
2.2.3 差错控制
TCP的差错控制机制是GBN和SR的结合体。采用了SACK,与SR更像。
2.2.3.1 GBN回退N步
N为窗口长度,即 已发送但未被确认的(分组)序号+可用并且还未发送的(分组)序号 = N
发送方:
- 可以连续发送多个分组而不用等待确认。但是可以发送的分组数是有限制的,不能超过N个。
- 超时。定时器记录了第一个已发送未被确认分组的ACK报文段的到达时间,如果超时,则发送方将重传这个分组以及它后面已发送还未被确认的所有分组(因为GBN采用的是累积确认)
- 当收到第一个已发送未被确认的分组的ACK时,base++,窗口向后挪动一位。
接收方:
由于GBN采用累计确认,所以接收方会丢弃所有到达的失序分组,不在缓存中存储失序分组。发送方需要将这些分组重传。如果分组k已接收并交付给应用层,那么所有序号比k小的分组都已经被接收。
2.2.3.2 SR选择重传
选择重传可以避免发送方重传不必要的分组。比如发送方正在发送0,1,2,3分组,1,2,3分组都已经收到接收方的ACK,但是分组0没有收到ACK,这有两种情况,1.分组0丢失,接收方没有收到。这时接收方收到的1,2,3分组都在TCP缓存中,发送方需要重传分组0,然后接收方发送ACK 0,并将连续的一段数据交付给上层(分组0的序号为接收窗口的基序号,该分组和以前缓存的起始于基序号的连续的分组一并交付)。2.分组0的ACK丢失或超时,发送方重传分组0,接收方丢弃,并发送一个ACK 0
2.2.4 TCP流量控制
如果某应用程序读取数据时相对缓慢,而发送方发送得太多、太快,发送的数据就可能使该连接的接受缓存溢出,后面到达的数据就不能被接收方接收。因此TCP提供了流量控制机制,避免缓存溢出。
发送方维护两个变量:LastByteSent和LastByteAcked。LastByteSent - LastByteAcked = 发送方发送到连接中但还未被确认的数据量。LastByteSent - LastByteAcked <= rwnd
接收方维护两个变量:LastByteRead和LastByteRcvd。LastByteRead表示接收方的应用程序从缓存中读取的数据流的最后一个字节编号,LastByteRcvd表示从网络中到达并已经放入接收方的接收缓存的数据流的最后一个字节编号。LastByteRcvd - LastByteRead = 缓存中的TCP数据量,LastByteRcvd - LastByteRead <= RcvBuffer。接收窗口rwnd = RcvBuffer - (LastByteRcvd - LastByteRead) 。接收窗口表示缓存中的剩余空间。
引用:《自顶向下》
rwnd通过TCP报文首部的Windows size字段指出。当主机A创建一条到主机B的TCP连接后,主机B为这个连接创建一个缓存RcvBuffer,初始值为rwnd,然后通过TCP报文段首部的窗口字段将rwnd通知给主机A,A还可以发送的字节量。
当rwnd逐渐减小为0时,发送方因被阻塞而不能再发送数据,但是此时接收方也没有TCP数据段发送给发送方,rwnd的状态不能及时更新,发送方不能知道接收方的缓存什么时候有空余空间,双方进入了死锁状态。
当接收方宣布接收窗口的值为0,发送方停止进一步发送数据,开始了“保持定时器”(persist timer),以避免连接的双侧进入死锁,发送方无法发出数据直至收到接收方修改窗口的指示。当“保持定时器”到期时,TCP发送方尝试恢复发送一个小的ZWP包(Zero Window Probe),期待接收方回复一个带着新的接收窗口大小的确认包。一般ZWP包会设置成3次,如果3次过后还是0的话,有的TCP实现就会发RST把链接断了。 ————维基百科
2.2.5 TCP拥塞控制
2.2.5.1 拥塞窗口
拥塞窗口表示为cwnd,是任何时刻内确定能被发送出去的字节数的控制因素之一,它和rwnd一同决定发送方能向网络中发送的数据量。。由发送方维护。当一条连接创建后,每个主机独立维护一个拥塞窗口并设置初始值为1MSS,MSS 的值一般为 1460 字节,然后根据链路的拥塞程度,将动态地改变拥塞窗口的大小。
LastByteSent - LastByteAcked为发送方已发送但未被确认的字节量,LastByteSent - LastByteAcked <= min {cwnd,rwnd},当LastByteSent - LastByteAcked = min {cwnd,rwnd}时,说明发送方不能再发送报文段了,需要等待两个窗口都有空闲容量。
拥塞窗口是阻止发送方至接收方之间的链路变得拥塞的手段发送方维护的,滑动窗口是为了防止接收方TCP缓存满了而导致的溢出。
2.2.5.2 慢启动
慢启动初始启动时,拥塞窗口cwnd被设置为1个MSS。每当传输的报文段首次被确认就增加1个MSS,这样一来,每个RTT内,cwnd的值呈现指数增加。
- 当cwnd >= ssthresh时,(说明链路上可能有拥塞)结束慢启动并且TCP转移到拥塞避免模式。
- 当存在一个因超时产生的丢包(即拥塞),TCP发送方将ssthresh(慢启动阈值)设置为cwnd/2,然后将cwnd设置为1MSS并重新开始慢启动。
- 当检测到3个冗余的ACK,TCP执行快速重传,并进入快速恢复状态。
2.2.5.3 拥塞避免
在慢启动阶段,cwnd=ssthresh,这个ssthresh的值为上次因为拥塞而设置的ssthresh=cwnd/2,所以当两者相等时,可能很快又会拥塞,因此cwnd不能再呈指数增加了。
在拥塞避免阶段,每个RTT只将cwnd的值增加一个MSS。
当出现超时产生的丢包时,TCP发送方将ssthresh设置为cwnd/2,然后将cwnd设置为1MSS并重新开始慢启动。
当出现丢包时(收到三个冗余ACK触发),ssthresh的值被更新为cwnd/2,并进入快速恢复状态。
2.2.5.4 快速恢复
🚨当收到3个冗余ACK,cwnd = ssthresh + 3*MSS ,然后重传丢失的报文段(快重传),当再次收到重复的之前ACK(说明接收方还是收到的报文段的序列号还是比他期望收到的序列号大,因此接收方继续发送冗余ACK),cwnd = cwnd + 1,最终当收到新的数据包的ACK后(丢失的包已经传到接收方了,收到的是丢失的报文段的ACK),说明可以恢复到正常的状态了,cwnd = ssthresh(拥塞避免阶段的门限值 6 ),进入拥塞避免阶段。
快重传:当接收方接收到的报文段的序号比他期望接收到的序列号大时,说明在数据包传输的过程中产生了丢包现象或者重新排序的现象,由于TCP采用累积确认,因此必须接收到有序的报文段,但允许接收方不丢弃失序报文段,同时因为不采用显式确认,所以接收方向发送方发送三个相同数据的冗余ACK(即对已经接收到的最后一个按序字节数据进行重复确认),发送方一旦收到三个冗余的ACK,就进行快速重传,重传冗余ACK后面的那个报文段。
为什么发送方等待3个冗余的ACK,而不是仅仅等待一个冗余ACK?
发送n,n+1,n+2但是由于网络原因n+1,n+2先到了,这时候会产生2个n的冗余ack,然后发送端就会重新发送n。大致原因是因为网络传输是不可靠的,丢包、乱序和复制等情况,如果出现三次以上DupAck的就认为丢包的可能性很高,可以进入快速重传机制。—-有待考证
😊TCP 保证可靠传输的机制有如下几种:
- 1)校验和 Checksum(稍作了解即可)
- 2)序列号和确认应答机制(重要)
- 3)重传机制(重要)
- 4)流量控制(滑动窗口协议)(非常重要)
- 5)拥塞控制(重要)
/protocol/拥塞机制.jpg 图片和上面写的TCP保证可靠传输的方法种类 来源:https://juejin.cn/post/6916073832335802382#heading-6
3.网络层协议
3.1 数据平面
3.1.1 IPv4
3.1.1.1 IP数据报结构
版本号:4bits,指示使用的是ipv4还是ipv6
首部长度:4bits,用来判断IP数据报的有效载荷的位置。大多数IP数据报不包含选项字段,所以一般首部长度为20字节。
服务类型:8bits,主要用来标识这个数据报是实时的还是非实时的,在网络拥塞的情况下会斟酌数据报的发送顺序—-我觉得
数据报长度:16bits,这是IP数据报的总长度,即首部加数据的长度。所以IP数据报的最大长度为2的16次方,即65535字节。由于下面的原因,IP数据报的长度一般不超过1500字节。
网络层数据包经过数据链路层的封装后,形成“帧”,帧头是14字节,帧尾是4字节。MTU为最大链路层帧长度,其实是帧中有效载荷的长度,即IP数据报的长度。MTU由链路层协议规定,一般以太网和PPP协议都具有1500字节的MTU,所以IP数据报的最大长度为1500字节,而帧长为1518字节。由于TCP/IP头部长度为40字节,所以MSS(最大报文段长度,应用层数据的长度)不能超过1460字节。
同时规定帧的最小长度为64字节,如果IP数据报长度小于64 - 18字节的话,在数据链路层封装的时候会利用填充字段将帧长度填充到64字节。
——–百度 and 《自顶向下》
16比特的标识、标志、13比特的片偏移:与IP分片有关。
由于在传输的过程中可能在不同的链路中采用的是不同的链路层协议,而不同的链路层协议可能有不同的MTU,所以有时候需要路由器对数据包分片。当IP数据报的长度超过MTU时,需要将IP数据报中的数据(TCP报文段)进行分片,然后将分片好的TCP报文段都加上IP首部,然后再都加上链路层首部。
*标识号:16bits,发送主机会将它发送的每个数据报的标识号加1,即刚从发送主机发送出去的时候每个数据报有唯一的标识号。如果在传输的过程中,路由器对它进行分片,则每个新的片(新的IP数据报)的标识号都是相同的,都是没有分片前的那个标识号。源和目的IP地址也是相同的。
*标志:分片后,最后一个片的标志为0,其他片的标志为1,说明如果目的主机发现标志为0时,说明目的主机已经收到了初始数据报的最后一个片。
*片偏移:指定该片应该放在IP数据报的哪个位置,进而可以按照正确的顺序组装TCP报文段,也防止丢失哪个片。
—已解决—-
下面说的都是在TCP发送缓冲区进行分片的情况,是对http报文进行分片,和上面的不一样,上面的是在传输的过程中由路由器进行的分片,而且是对TCP报文段分片。
11111.如果TCP发送缓冲区的数据大小超过MSS,发送主机会将它分片,但是主机如何标识TCP缓冲区中的分片后的数据是来自同一个http报文段,以及如果一个报文段的长度特别小,那么主机会等待TCP缓冲区内的数据量多一点时,再发送,但是这时候应该是将缓冲区中的数据一起,并且加上一个TCP首部,这还能区别是不同的http报文段吗?————–这应该是通过http的Content-Length字段指明body的长度。
22222.但是如果tcp缓冲区分片,导致一个http请求被分成多个分片放入不同的TCP报文段中,然后有一个TCP报文段丢失了,这时如何使接收方接收到完整的http报文? ————-发送主机会重传这个报文段,因为TCP有差错检验机制,和累积确认,接收到的报文段会先放在TCP接收缓存中,如果是按序的,就直接交付给上层,如果不是按序的,接收方会发送三个冗余ack,进行快速重传。
寿命:4bits,TTL字段用来防止数据包在链路中形成环路。每经过一台路由器,TTL字段就减一。当TTL字段减为0时,数据包将要被丢弃。
协议:用来标识使用的是TCP协议(6)还是UDP协议(17),或者是其他协议。指示IP数据报的数据部分使用的是哪个协议,应该交给哪个运输层协议。它是网络层和运输层绑定到一起的粘合剂。
首部检验和:16bits,将IP首部每2个 字节作为一个数,依次对这些数进行反码运算,然后将运算结果填入到首部检验和字段,当路由器收到IP数据报后,会再次运算检验和(TTL字段和可选的选项字段的值在运输的过程中会发生改变),如果和首部检验和字段不一样,就会丢弃这个数据包。
为什么TCP/IP在网络层和运输层都执行检验和的差错检测?
TCP/UDP检验和是对整个TCP/UDP报文段求,并将和的反码放入检验和字段中,而IP检验和仅仅对IP首部求检验和。
TCP/UDP和IP不一定都属于同一个协议栈,IP数据报有可能携带的数据字段不是使用的TCP/UDP协议。而其他协议不一定有检验和。(TCP可以运行在不同的协议上,如ATM)
————《自顶向下》
源和目的IP地址:均为32bits
选项:32bits,一般不使用选项字段,这样可以节约开销。
数据:IP数据报携带的数据,即有效载荷。数据字段包含的是运输层报文段。该字段可以承载TCP、UDP报文段,也可以是其他类型的数据,如ICMP报文段。
3.1.1.2 IP编址
分类编址
最开始的时候,IP地址的网络部分被限制为长度为8、16、24比特,这被称为分类编址。具有8、16、24比特的子网地址的子网被成为A、B、C类网络。但是这种方法十分有局限性,比如,如果一个组织有2000台主机,而C类网络能容纳2的8次方-2台=254台主机,不够,而B类网络能容纳2的16次方-2台=65534台主机,又太大了,会浪费很多地址。
CIDR无类别域间路由选择
由于分类编址的局限性,因此提出了CIDR,这个策略可以划分不同的网络部分,只需要在用点分十进制表示的IP地址的后面加上 / 和网络部分的位数就可以了,它可以根据一个组织中的主机数来分配最小可以容纳这个主机数的子网。一个地址的/x部分,即32-x比特可以用来区分同一个网络前缀的子网内部的不同主机。
3.1.1.3 DHCP协议分配IP地址
ICANN组织管理着所有的IP地址,所有的ISP都会先向ICANN申请一块很大的地址,然后当在某个ISP中又有网络管理员,用来从ISP的大地址中给某个组织分配子网的IP地址。当一个组织得到一块子网地址后,会利用这个地址内的DHCP服务器给新进来子网的主机分配IP地址。如果这个子网里没有DHCP服务器,则需要一个DHCP中继代理器(一个路由器),它知道可以给这个子网内的主机分配IP地址的DHCP服务器的地址。
DHCP协议:动态主机配置协议。
111.首先新进子网的主机还没有IP地址,它先使用0.0.0.0作为本主机的源IP地址,向这个子网中发送一个DHCP发现报文,目的IP地址是255.255.255.255,利用UDP报文向端口67发送该报文,即将这个发现报文广播到子网的所有主机和路由器上。
222.DHCP服务器收到发现报文后,就向该子网的所有节点广播,发送一个DHCP提供报文,里面的源IP地址是DHCP服务器的地址,目的IP地址是255.255.255.255,报文中携带给这个主机分配的IP地址和它的租用期等相关信息。
333.因为该子网中可能有一个或多个DHCP服务器,所以可能接收多个DHCP提供报文,那么这个主机就选择一个DHCP服务器,向它发送DHCP请求报文,源IP地址还是0.0.0.0,目的IP地址是这个服务器的IP地址,里面携带新分配的IP地址以及它的租用期。
444.DHCP服务器收到后仍然广播发送一个DHCP ACK报文,当用户收到这个报文后,就可以使用新分配的IP地址了。
yiaddr:DHCP向客户分配的IP地址,这个服务器推荐客户机用这个IP地址。
3.1.1.4 NAT网络地址转换
当某个组织被分配一块地址后,随着该子网中的主机数越来越多,很有可能这些地址不够分配,所以现在就出现了一个方法:网络地址转换。即这个子网只给路由器分配一个IP地址,将与路由器相连的主机群定义为具有专用地址的地域,就是这个地址只有在这个地域网络中才有效,到互联网中就无效。
它是如何实现的呢?在路由器(中间盒)中有一个NAT转换表,LAN端是这些主机的IP地址和端口号,WAN端是路由器的IP地址和新分配的端口号。
每次主机向互联网发送数据包时,路由器会根据NAT表将重写源地址和端口号(这个端口号是路由器选择的未在NAT转换表中出现过的端口号,这样才可以唯一定位主机和对应端口号,并在NAT表中增加这个记录),接收外界数据包时,路由器通过查询NAT表,重写目的IP地址和端口号,并向这个主机转发该数据报。
WAN端 | LAN端 |
---|---|
138.76.29.7,5001 | 10.0.0.1,3345 |
138.76.29.7,4000 | 10.0.0.2,1253 |
比如,138.76.29.7是路由器与互联网连接的IP地址,10.0.0.4是与专用网络连接时使用的IP地址。
3.1.2 IPv6
版本:标识这个IP数据报是IPv6
流量类型:8bits,就是服务类型,是实时数据还是非实时数据。
流标签:20bits,——不太理解——-
有效载荷:16bits,给出了IPV6携带的数据的字节数量。IPv6的首部是定长20字节。
下一个首部:数据报携带的数据应该交付给哪个运输层协议。
跳限制:即数据报的寿命,TTL
源和目的IP地址:ipv6将IP地址的长度从32位扩展到128位,还引入了任播地址。
可以利用隧道进行IPV4到IPv6的迁移。隧道就是两台IPv6路由器中间的中间IPv4路由器的集合。通过隧道的时候,将IPv6数据报作为有效载荷封装到IPv4数据报中,在IPv4路由器中传递,到隧道出口再将IPv6数据报取出,交给IPv6路由器。
IPv6与IPv4的区别:1.取消了在传输过程中的分片和重新组装。如果路由器发现IP数据报的长度超过MTU时,直接丢弃这个数据报,并向发送方发送一个“包太大”的ICMP报文。2.取消了选项字段。3.取消了首部检验和,因为运输层和数据链路层的协议已经执行了检验操作,在网络层再进行检验增加了开销,比较耗时。————在上面解释为什么IPv4需要进行检验的时候说运输层可能不是TCP/UDP协议,所以可能没有检验和的操作,所以IP数据报中需要进行检验和的操作,现在IPv6里面又说这两层都进行了检验和操作,这不是矛盾了吗?
3.2 控制平面
3.2.1 OSPF
OSPF:开放最短路径优先,是自治系统内部的路由选择协议。它是一种链路状态协议,使用洪泛链路状态信息和链路状态路由选择算法LS。所谓洪泛,就是在AS内部,每当一条链路的状态发生变化,与它相连的路由器将向自治系统内所有的其他路由器广播路由选择信息。先通知与这个路由器端口连接的所有路由器,然后通知与之相连的其他路由器,直到通知到AS的所有路由器。其实,即使链路状态不发生改变,每隔至少30min路由器也会周期性的广播一次链路状态信息,目的是增强链路算法的健壮性。
路由器间如何交流?根据OSPF协议,路由器发送由IP数据报承载的OSPF报文。
3.2.2 BGP
BGP:边界网关协议,自治系统间的路由选择协议。
通告BGP信息:当一个AS内新增一个具有某个前缀的子网,与子网相连的路由器会通过BGP协议,将这个子网通告给其他AS。在每个AS内,有连接到其他AS中路由器的网关路由器,也有仅连接在当前AS的内部路由器。在AS内部转发的BGP报文称为iBGP,在AS间转发的BGP报文称为eBGP。两个路由器利用BGP协议进行通信时,他们通过使用179端口的半永久TCP连接交换路由选择信息。
确定传输的路由:当某个AS的一台路由器向这个子网发送数据包时,这个路由器到这个子网可能有多条路径,所以路由器需要先确定一个路由。采用的策略:1.热土豆路由选择。路由器仅考虑将分组送出该AS的最短路径,而不管这个AS到目的地其他路径的开销。分组好像”烫手的山芋“。 2.路由器选择算法。路由器被管理员指派本地偏好值,选择具有最高本地偏好值的路由,如果有多条相同本地偏好的路由,那么BGP使用DV算法(看该AS到子网所在的AS的多条路径中,哪个AS跳数最少,看AS-PATH)决定路径。 3.如果经过上面的筛选,还有多条路径,那么就开始热土豆路由选择。4.如果还有,路由器使用BGP标识符来选择路由。
3.2.3 ICMP
ICMP报文承载在IP数据报中,由路由器发送给这个分组对应的发送主机上。
利用这个报文还可以跟踪一台主机到世界上任意一台主机之前的路由的名字和IP地址。