网络七层模型
物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
TCP/IP网络五层模型
物理层、数据链路层、网络层、传输层、应用层
应用层
TCP(HTTP)长链接和短连接的区别
为什么说既是HTTP长连接也是TCP长连接
- HTTP协议的长连接和短连接,本质上是TCP协议的长连接和短连接
- HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议
- IP协议主要解决网络路由和寻址问题
- TCP协议主要解决如何在IP层之上可靠地传递数据包,使得网络上接收端收到发送端所发出的所有包,并且接受顺序与发送顺序一致。TCP协议是可靠的、面向连接的。
TCP短连接
- client向server发起连接请求,server接到请求,然后双方建立连接。
- client向server发送消息,server回应client,然后一次读写就完成了,
- 这时候双方任何一个都可以发起close操作,不过一般都是client先发起close操作。
- 一般的server不会回复完client后立即关闭连接的,
- 短连接一般只会在client/server间传递一次读写操作
TCP长链接
- client向server发起连接,server接受client连接,双方建立连接。
- Client与server完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。多次HTTP请求共用同一个TCP连接。
TCP长连接中的连接问题 连接数的问题
- Client与server之间的连接如果一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server早晚有扛不住的时候
- server需要采取一些策略:关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致server端服务受损;以客户端机器为颗粒度,限制每个客户端的最大长连接数 连接是否存在
- 连接中的保活机制。在一段时间内连接处于非活动状态(一般是两个小时),那么服务器端将向客户端发送一个报文。
- 没有收到回应,则在一定时间间隔内还会继续发送。当发送次数达到阈值(保活次数)后,确认对方主机不可达,断开连接。发送探测消息
- 相对应的客户端的状态
- 对方主机正常,但对方不想赢,超过次数后关闭
- 对方正常,但因为网络原因没收到确认报文
- 对方主机崩溃了,不会响应报文
- 对方主机崩溃然后重启,服务器会受到响应报文,然后关掉链接
- 相对应的客户端的状态
TCP Keep-Alive 和 HTTP Keep-Alive
TCP Keep-Alive
- 应用层实现 原因
- 每次请求都是建立 TCP -> 请求资源 -> 响应资源 -> 释放连接
- 短连接方式太累了,一次只能请求一个资源。所以想能不能在第一个 HTTP 请求完后,先不断开 TCP 连接,让后续的 HTTP 请求继续使用此连接 请求—应答模式
- 客户端发起请求,服务端会返回响应
- HTTP 的 Keep-Alive 就是实现了这个功能,可以使用同一个 TCP 连接来发送和接收多个 HTTP 请求/应答,避免了连接建立和释放的开销,这个方法称为 HTTP 长连接。
- HTTP1.0 中是默认关闭的。通过 headers 设置”Connection: Keep-Alive”开启。
- HTTP的Keep-Alive是HTTP1.1中默认开启的功能。通过headers设置”Connection: close “关闭。
HTTP Keep-Alive
- 内核态实现 TCP 的保活机制
- 如果两端的 TCP 连接一直没有数据交互,达到了触发 TCP 保活机制的条件,那么内核里的 TCP 协议栈就会发送探测报文。
- 如果对端程序是正常工作的。当 TCP 保活的探测报文发送给对端, 对端会正常响应,这样 TCP 保活时间会被重置,等待下一个 TCP 保活时间的到来。
- 如果对端主机崩溃,或对端由于其他原因导致报文不可达。当 TCP 保活的探测报文发送给对端后,没有响应,连续几次,达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡。
- TCP 保活机制在双方没有数据交互的情况,通过探测报文,来确定对方的 TCP 连接是否存活,这个工作是在内核完成的。
HTTP
请求报文
- 请求报文以ASCII码传输,建立在TCP/IP协议上的应用层规范
- 由请求行(request line)、请求头部(header)、空行和请求数据组成
- 请求行:由请求方法、URL字段以及HTTP协议版本字段三个部分组成,它们用空格分开。
- 请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT
- GET:客户端要从服务器读取数据时,点击网页上的链接,或者通过在浏览器的地址栏输入网址来浏览网页的,使用的都是GET方式。
- 要求服务器将URL定位的资源放在响应报文的数据部分
- 请求参数和对应的值附加在URL后面,利用问号(?),代表URL的结尾和请求参数的开始
/index.html?id=1&password=123
- 通过GET的方式传递的数据直接显示在地址上,将请求以链接的方式发送给接收方
- 请求参数和对应的值附加在URL后面,利用问号(?),代表URL的结尾和请求参数的开始
- 不能传递私密的数据
- 地址的字符长度限制
- 大量的数据传输,不适合使用GET方式。
- 要求服务器将URL定位的资源放在响应报文的数据部分
- POST:将请求参数封装在HTTP的请求数据中
- 各个WEB服务器会规定对post提交数据大小进行限制
- 可以不显示在URL中
- POST方法向服务器提交数据,比如表单的数据的提交。GET的方法一般用于获取/查询资源信息
- GET:客户端要从服务器读取数据时,点击网页上的链接,或者通过在浏览器的地址栏输入网址来浏览网页的,使用的都是GET方式。
- 请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT
- 请求头:由键值对组成,关键字和值之间用 : 分开,一般用unordered_map来存储请求头。
- 参数
- User-Agent:操作系统、浏览器和其它属性告诉服务器
- Accept:客户端可识别的响应内容类型列表:eg:Accept:image/gif,表明客户端希望接受GIF图象格式的资源
- Accept-Language:客户端可接受的自然语言
- Accept-chartset:可接受应答的字符集
- Accept-Encoding:可接受的编码压缩格式
- HOST:请求的主机名称
- Connection:连接方式(close或keep-alive)
- Cookie:存储于客户端扩展字段,向同一域名的服务端发送该域的cookie
- Authorization:证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含Authorization请求报头域的请求,要求服务器对其进行验证。
- 参数
- 空行
- 请求体:请求数据不再GET方法中使用,在POST方法中使用。
- POST方法适用于客户端提交表单。
- 与请求数据相关的最常使用的请求头是包体类型 Content-Type 和包体长度 Content-Length
- 请求行:由请求方法、URL字段以及HTTP协议版本字段三个部分组成,它们用空格分开。
响应报文
- 由状态行、响应头部、空行和响应包体四个部分组成
- 状态行:由HTTP协议版本,状态码和状态码描述文本三个部分组成,它们之间用空格隔开
- 状态码:三位数字组成;第一位定义了响应的类别,可能有五种取值
- 1xx:服务端已经接收到客户端请求,客户端可以继续发送请求;
- 2xx:服务端已经成功接收请求并处理
- 200:ok
- 3xx:服务器要求客户端重定向
- 4xx:客户端请求有问题
- 400:请求语法有问题
- 401 Unauthorized:请求未经授权,必须与Authorization请求报头域一起使用
- 403 Forbidden:服务器收到请求但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因
- 404 Not Found:请求的资源不存在
- 5xx:服务端未能正常处理客户端的请求出现错误
- 500:服务器发生错误,无法完成客户端请求
- 503 Service Unavailable:服务器当前不能处理客户端请求,一段时间之后可能恢复正常
- 状态码:三位数字组成;第一位定义了响应的类别,可能有五种取值
- 响应头:
- Vary:指示不可缓存的请求头列表
- Server:服务器用来处理请求的软件信息及其版本
- Connection:连接方式
- www-Authenticate:被包含在401 (未授权的)响应消息中
- 响应体:服务器返回给客户端的文本信息
HTTP的无状态性
- 状态行:由HTTP协议版本,状态码和状态码描述文本三个部分组成,它们之间用空格隔开
- 同一个客户端第二次访问同一个服务器上面的页面时,服务器无法得知这个客户端曾经访问过
- HTTP的无状态性简化了服务器的设计,是服务器更容易支持大量并发的HTTP请求。
- 采用请求-响应的模型。客户端向服务端发送一个请求报文,服务端以一个状态作为回应。
- 当使用普通模式,即非keep-alive模式时,每个请求-应答都要重新建立一个连接,连接完成后立即断开
- Keep-Alive: timeout=5, max=100,表示这个TCP通道可以保持5秒,max=100,表示这个长连接最多接收100次请求就断开。
- 是一个无状态协议,这意味着每个请求都是独立的,Keep-Alive 没能改变这个结果。
- 唯一能保证的就是当连接被关闭时你能得到一个通知,
- 不让程序依赖于 Keep-Alive 的保持连接特性,否则会有意想不到的后果。
HTTP与HTTPS
一个安全的机制应该满足三个特性:机密性,完整性,不可否认性
- http协议不安全
- 机密性,由于使用明文进行通信,导致信息会被窃听泄露
- 完整性,一段裸奔的明文在网络上传递,会被轻而易举的篡改
- 不可否认性,由于http的请求和响应不会对通信方的身份进行确认,导致很容会被欺骗,而且用户无法察觉
- https:HTTP通信接口部分用SSL和TLS协议代替而已。
- HTTP直接和TCP通信。
- HTTPS是SSL协议位于TCP和HTTP协议之间的通信方式。
- SSL:
- 解决机密性。对请求和应答消息进行加密。公钥加密效率比较低,对称加密效率较高。因此对于密钥协商这块,使用公钥两方协商密钥,然后用密钥执行对称加密对消息加密
- 完整性。依靠单向散列函数实现,比如MD5或者SHA1
- 不可否认性。依靠数字签名实现。
- SSL:
- https加密算法
- 首先由客户端发送请求
- server得到请求后,将证书(包括公钥)返回
- 由客户端对证书进行验证
- 生成随机数,使用公钥对随机生成的client key进行加密,传递给server
- server得到后,利用私钥解密,并将请求的数据通过client key进行对称加密并传递
- 得到后利用client key对请求数据进行对称解密
SSL/TLS
页面访问过程 DNS过程 IP头部TTL的traceroute
访问网页过程
URL解析 -> http请求确定-> DNS解析 -> tcp/ip封装 -> 数据链路层封装 -> 网卡封装 -> 交换机 -> 路由器
- 浏览器解析URL
https://www.webserver.com/dir/file
- 解析访问协议HTTP/HTTPS、web服务器名、文件路径名
- 产生HTTP请求
- 根据请求封装get和post请求
- DNS解析
- 在发送给服务器地址前,查询服务器对应IP
- 走本地网络协议栈
- DNS解析后,将HTTP传输工作交给操作系统的协议栈
- HTTP的本质是基于TCP/IP,在发送报文之前,先确定连接,建立后经过TCP/IP协议封装形成网络报文(IP头部、TCP头部、HTTP报文)然后经过数据链路层封装(在IP头部前加入MAC头部),最终从本地发送的报文为(MAC头部、IP头部、TCP头部、HTTP报文)
- 经过本机网卡
- 使用网卡转换电信号,加入报头和起始帧分界符,在末尾加上帧校验序列(报头和起始帧分界符、MAC头部、IP头部、TCP头部、HTTP报文、FCS)
- 到达交换机
- 内部维护了一个MAC地址表,通过这个表查找对应MAC地址所在的端口上,从这个端口转发出去。
- 当地址表中找不到指定的 MAC 地址时,交换机无法判断应该把包转发到哪个端口,只能将包转发到除了源端口之外的所有端口上,无论该设备连接在哪个端口上都能收到这个包。只有相应的接收者才接收包,而其他设备则会忽略这个包。
- 路由器
- 收到包后会解开MAC地址查看其目的IP地址,根据路由表中的转发规则选择转发,如果没有匹配规则就使用默认路由,路由表中子网掩码为 0.0.0.0 的记录表示默认路由。
- 路由器有MAC地址的,所以他可以成为接收方和发送方。
- 知道对方的 IP 地址之后,接下来需要通过 ARP 协议根据 IP 地址查询 MAC 地址,并将查询的结果作为接收方 MAC 地址。路由器也有 ARP 缓存,因此首先会在 ARP 缓存中查询,如果找不到则发送 ARP 查询请求。
DNS解析
目的
- 为其他应用层协议工作的,将用户提供的主机名解析为ip地址
分类
- 根DNS服务器
- 顶级DNS服务器
- 二级DNS服务器
过程 递归查询
- 检查浏览器缓存,是否存在域名与IP映射关系
- 系统本地:一般在hosts文件中
- 本地域名服务器: 迭代查询
- 本地域名服务器查询根域名服务器,告诉你去顶级域名服务器查询
- 本地域名服务器查询顶级域名服务器(com服务器),引导去二级域名服务器查询
- 本地域名服务器查询二级域名服务器(baidu.com服务器),引导去三级域名服务器查询
- 本地域名服务器查询三级域名服务器(mail.baidu.com服务器),
- 如果有则返回映射关系,则本地域名服务器加入自身的映射表中,方便下次查询或其他用户查找,
- 同时返回给该用户的计算机,没有找到则网页报错
- 如果还有下级服务器,则依此方法进行查询,直至返回映射关系或报错
DNS通信请求
- 所有DNS请求和回答报文使用的UDP数据报经过端口53发送
- 因为一次UDP名字服务器交换可以短到两个包:一个查询包、一个响应包。一次TCP交换则至少包含9个包:三次握手初始化TCP会话、一个查询包、一个响应包以及四次分手的包交换。
- 考虑到效率原因,TCP连接的开销大得,故采用UDP作为DNS的运输层协议
- 这也将导致只有13个根域名服务器的结果。
- DNS的规范规定了2种类型的DNS服务器,一个叫主DNS服务器,一个叫辅助DNS服务器(做冗余备份)
- 一个区中主DNS服务器从自己本机的数据文件中读取该区的DNS数据信息
- 辅助DNS服务器则从区的主DNS服务器中读取该区的DNS数据信息
- 辅助DNS服务器启动时,它需要与主DNS服务器通信,并加载数据信息,这就叫做区传送
- 区域传送时使用TCP
- 辅助域名服务器会定时(一般是3小时)向主域名服务器进行查询以便了解数据是否有变动,如有变动,则会执行一次区域传送,进行数据同步。
- 数据同步传送的数据量比一个请求和应答的数据量要多得多
cookie 和 session
- cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户的状态,就使用response向客户端浏览器颁发一个cookie。客户端浏览器会把cookie保存起来。当浏览器再次请求该网站时,浏览器就会把请求地址和cookie一同给服务器。服务器检查该cookie,从而判断用户的状态。服务器还可以根据需要修改cookie的内容。
- session是另一种记录客户状态的机制。不同的是cookie保存在客户端浏览器中,而session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是session。客户端浏览器再次访问时只需要从该session中查找该客户的状态就可以了。
- cookie机制是通过检查客户身上的“通信证”
- 那么session机制就是通过检查服务器上的“客户明细表”来确认客户身份。
traceroute原理
目的
- 当源主机A向目标主机B发送消息,发现消息无法送达。此时,可能是某个中间节点发生了问题,可以通过traceroute进行初步的检测,定位网络包在是在哪个节点丢失的 原理
- 在IP头部中有TTL字段,其设置最多经过节点数
- 每经过一个中间节点,再向下一个节点转发数据前,都会将TTL减1。如果TTL不为0,则将数据报转发到下一个节点;否则,丢弃数据报,并返回错误。
- TTL = 0 时,报错信息是ICMP报文
- 每经过一个中间节点,再向下一个节点转发数据前,都会将TTL减1。如果TTL不为0,则将数据报转发到下一个节点;否则,丢弃数据报,并返回错误。
- 源主机向目标主机发送IP数据报文,并按顺序将TTL设置为从1开始递增的数字(假设为N),导致第N个节点(中间节点 or 目标主机)丢弃数据报并返回出错信息。源主机根据接收到的错误信息,确定到达目标主机路径上的所有节点的IP,以及对应的耗时。 特点
- 使用UDP协议
- 如果传输成功如何设置traceroute
- 将目标端口设置为较大的值( 33434 - 33464),避免目标主机B上该端口有在实际使用。
- 当报文到达目标主机B,目标主机B发现目标端口不存在,则向源主机A发送ICMP报文(Type=3,Code=3),表示目标端口不可达。所以知道已经到达了目标主机
UDP实现TCP
原因
- 慢启动和拥塞避免的缺点 处理
- 在应用层封装 处理
- 增加ack机制,确保能发送到对端
- 增加seq机制,实现顺序化传输
- 需要用队列实现缓冲区,主要是为了重传
- 校验机制
传输层
TCP UDP
TCP 与 UDP
不同
- 连接
- TCP:传输数据前要先建立连接。
- UDP:不用
- 可靠性
- TCP:传输的数据无差错,不丢失,不重复,而且按序到达。
- UDP:尽最大努力交付,不保证可靠性。
- 服务对象
- TCP:点到点服务,只能有两个端点。
- UDP:一对一、一对多、多对多、多对一交互
- 传输方式
- TCP:面向字节流的,但保证顺序和可靠。
- UDP:面向报文,不会出现该问题
- 拥塞,流量控制
- TCP:有拥塞控制和流量控制机制,保证数据传输的安全性。
- UDP:没有拥塞控制,网络出现拥塞时,不会使得源主机发送数据速率降低
- 首部开销
- TCP首部开销20字节,可变大
- UDP首部8字节并且是固定不变的
- 分片不同
- TCP:数据大小如果大于 MSS 大小,则会在传输层进行分片
- 目标主机收到后,也同样在传输层组装 TCP 数据包
- 如果中途丢失了一个分片,只需要传输丢失的这个分片。
- MSS:为MTU值减去IPv4 Header(20 Byte)和TCP header(20 Byte)得到。
- 引入原因
- 对数据链路层IP层分片,当⼀个超过MTU大小的数据(TCP 头部 + TCP 数据)要发送,那么 IP 层就要进行分片,保证每⼀个分片都小于 MTU,当如果⼀个 IP 分片丢失,整个 IP 报文的所有分片都得重传。接收方TCP报文不完整后不会响应ACK的,那么TCP发送方就会触发超时重传,重发整个TCP报文段。
- TCP为了避免被发送方分片,它主动把数据分成小段再交给网络层。建立连接的时候会剔除IPHeader和TCPHeader,剩下的就是协商的MSS值,当TCP发现超过MSS后就会分片,这样形成的IP包长度也就不会大于MTU了,也就不用IP分片了,保证不会发生全部的重传
- UDP 的数据大小如果大于 MTU 大小,则会在 IP 层进行分片
- 目标主机收到后,在 IP 层组装完数据,接着再传给传输层
- 如果中途丢了一个分片,则就需要重传所有的数据包,这样传输效率非常差
- MTU:硬件规定 UDP首部
- TCP:数据大小如果大于 MSS 大小,则会在传输层进行分片
- 源端口号:需要对方回信时候可以用,不需要回复可以设置为0
- 目的端口:必须有,交付报文要用到
- 长度:UDP首部和UDP数据的长度和,最小为8个字节。因为首部就8个字节
- 校验和:发送端计算,接收端验证,为了发现在数据收发间有无改动 TCP首部
- 源端口:
- 目的端口:
- 32位序列号:表示当前tcp数据第一个字节在整个字节流中的相对位置。
- 第一个报文的序号值被系统初始化为某个随机值ISN,后序的TCP报文的序号值被设置成ISN+报文所携带数据的第一个字节序号。
- 比如某个报文要传输的数据是字节流中的1025-2048字节,序号就是ISN+1025
- 32位确认号:响应收到的TCP报文段,ack就是收到的32位序列号+1
- 4位头部长度:表示TCP头部由多少个4字节组成。因为最多能表示15,所以15*4=60
- 标志位(6位)
- URG:报文段的紧急指针是否有效
- ACK:表示确认号是否有效
- PSH:接收端应用程序是否:应该立即从TCP缓存中读出该数据。
- SYN:用于数据同步,有syn的报文段成为同步报文段。
- FIN:表示数据是否发送完毕。FIN=1表示数据发送完毕,可以释放连接。有fin标志的成为结束报文段。
- RST:位置为1时表示tcp连接中出现异常必须强制断开
- 16位窗口大小:告诉对方自己的接收缓冲区还能容纳多少数据,这样可以控制对方的发送速度
- 16位校验和:检验数据的正确性,保证可靠性。不仅校验头部,也校验数据部分
- 16位紧急指针:标记紧急字段在数据中的位置
- 以上一共20字节,还有40字节可选用字段
- 数据部分 TCP特点
- 面向连接:一定是「一对一」才能连接
- 可靠的:无论的网络链路中出现了怎样的链路变化,TCP 都可以保证一个报文一定能够到达接收端;
- 字节流:
- 无论我们消息有多大都可以进行传输。
- 当前一个消息没有收到的时候,即使它先收到了后面的字节,那么也不能扔给应用层去处理
- 同时对重复的报文会自动丢弃。 一对一的最大连接数
- 首先服务器端地址确定了,源端口确定了,那么只有客户端的IP数和目标端口不确定,得到理论$2 ^ {32} \times 2^{16} = 2^{48}$
- 实际中
- 内存限制,每个TCP都占用内存
- 文件描述符限制,会通过
ulimit
配置文件描述符数目
TCP原理 TCP三次握手
- 开始建立连接。服务器主动监听某个端口,处于
LISTEN
状态 - 第一次握手
- 客户端会随机初始化一个序号,将此序号置于 TCP ⾸部的序列号字段中,同时把 SYN 标志位置为 1 ,表示这是一个 SYN 报⽂。
- 把第⼀个 SYN 报⽂发送给服务端,表示向服务端发起连接,该报⽂不包含应⽤层数据,之后客户端处于 SYN-SENT 状态。
- 第二次握手
- 服务端随机初始化⾃⼰的序列号,将此序号填⼊TCP ⾸部的「序列号」字段中
- 把 TCP ⾸部的「确认应答号」字段填⼊ 「客户端发送的序列号 + 1」, 把 SYN和 ACK 标志位置为 1 。
- 把该报⽂发给客户端,该报⽂也不包含应⽤层数据,之后服务端处于SYNRCVD 状态。
- 第三次握手
- 向服务端回应最后⼀个应答报⽂,应答报⽂ TCP ⾸部 ACK 标志位置为 1 ,其次「确认应答号」字段填⼊ 服务端发送的序列号 + 1 ,把报⽂发送给服务端
- 携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态
- 等到服务器收到客户端的应答报⽂后,也进⼊ ESTABLISHED 状态
- 只有第三次可以携带数据。因为经过两次握手,客户端收到ack确认报文段之后就已经建立了连接,表明服务端的接受和发送能力是正常的,
- 等到服务器收到来自客户端你的确认报文后,也表明客户端的接受和发送能力是正常的,就可以进行正常的全双工通信了。 为什么是三次握手
- TCP是一个全双工的通信方式,因此可以理解为两条单向通道。
- 客户端发送FIN报文段给服务器端,服务器端发送ACK报文段这一个过程是一个单向通道的建立过程,表明服务器是完好的,可以收发数据。
- 服务器到客户端这条通道同理也需要相同的过程,服务器发送FIN同步报文段给客户端,客户端返回一个ACK确认帧给服务器,这样一个全双工的通道就建立好了
- 而服务器发送的ACK确认帧和服务器发送的FIN同步报文段完全可以放在一起,不用分两次发送,所以就造成了三次握手。 三次握手好处
- 阻止重复的历史连接
- 当网络拥堵的情况下,三次握手时一个客户端连续多次发送SYN建立连接的报文,造成一个旧的SNY报文比新的SYN早到服务器端。
- 客户端收到后会根据自身的上下文判断这是否是一个历史连接
- 如果是历史连接则发送一个RST报文给服务器端表示终止。
- 同步双方的初始序列号
- “序列号”是TCP保持可靠顺序传输的关键
- 拥有序列号之后可以做的事
- 去除重复连接
- 根据数据报的序列号按序接收
- 可以标识发出去的数据包有哪些被接受了
- 两次握手只能保证一方的序列号成功被对方接受,而不能保证双方序列号都被互相接受。
- 拥有序列号之后可以做的事
- “序列号”是TCP保持可靠顺序传输的关键
- 避免资源浪费
- 四次已经优化成三次了,再多的话就浪费没必要了。 初始序列号(ISN)
- TCP 发送方的字节数据编号的原点,告诉对方我要开始发送数据的初始化序列号
- ISN 是动态生成、客户端和服务端的初始序列号 ISN 是不相同的
- 原因:
- 防止伪造相同序列号的TCP报文被接受
- 使得通信双方根据序号将不属于本次连接的报文段丢弃掉 半连接队列(SYN队列)和全连接队列(accept队列)
- 原因:
- 半连接队列:服务器第一次收到客户端的
SYN
之后,就会处于SYN_RCVD
状态,服务器会把这种状态下请求连接放在一个队列里。队列称为半连接队列。 - 在第三次握手后,客户端收到ACK确认报文后,从
SYN
队列中移除放到accept
队列中,通过调用accept()
socketAPI 从accept队列中取出连接 - 如何增大半连接队列
- 大部分情况是由于后端服务处理不过来,即连接建立后,accept速度过慢导致应该从服务性能优化上去解决问题
- 如何增大全连接队列
- 大部分情况是由于后端服务处理不过来,即连接建立后,accept速度过慢导致应该从服务性能优化上去解决问题。 SYN攻击
- 短时间伪造不同 IP 地址的 SYN 报文,服务器端的半连接队列被占满,正常用户发送的STN报文无法被存储,服务器无法提供其他服务。
- 解决
* 通过修改 Linux 内核参数,控制队列大小和当队列满时应做什么处理。
- 扩大队列大小,队列满时对新的SYN报文直接回复RST,然后丢弃掉
- 当SYN队列满了之后,服务器如果再次收到SYN同步报文,服务器计算cookie值,以SYN+ACK中的序列号返回给客户端。当服务端再次收到客户端的ACK时会检查其合法性,如果合法再放到ACCEPT队列、 三次握手携带数据
- 扩大队列大小,队列满时对新的SYN报文直接回复RST,然后丢弃掉
- 第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。
- 如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据,疯狂着重复发 SYN 报文
- 这会让服务器花费大量的内存空间来缓存这些报文,这样服务器就更容易被攻击了
- 第三次握手,此时客户端已经处于连接状态,他已经知道服务器的接收、发送能力是正常的了,所以可以携带数据是情理之中。 TCP四次挥手
- 如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据,疯狂着重复发 SYN 报文
- 第一次挥手
- 客户端打算关闭连接,此时会发送⼀个 TCP首部 FIN 标志位被置为 1 的报⽂,也即 FIN 报⽂,之后客户端进入FIN_WAIT_1 状态。
- 第二次挥手
- 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。
- 第三次挥手
- 等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态
- 第四次挥手
- 服务器收到了 ACK 应答报文后,就进入了 CLOSED 状态,至此服务端已经完成连接的关闭。客户端在经过 2MSL 一段时间后,自动进入 CLOSED 状态,至此客户端也完成连接的关闭。
为什么是四次挥手
- 如果要关闭这两条管道的通信要几个步骤
- 第一次客户端向服务器端发送FIN通知服务器端我这边要断掉了,不给你发数据了,这一次是必然的。
- 客户端给服务器端恢复一个ACK表示你关我知道了。
- 由于服务器端要处理一些数据然后发送给客户端,所以第二次和第三次是无法合并到一起的。
- 所以当服务器端收到客户端的FIN报文段后,必须马上回一个ACK确认报文表示可以管
- 但此时可能服务器端有一些数据需要处理,所以说等处理完数据我再发一个FIN关闭报文给客户端告诉客户端我这边也要关闭了。
TIME_WAIT状态 只有主动关闭的一方才有TIME_WAIT状态
- 客户端收到了来自服务器的带有FIN、ACK的结束报文段后并没有直接关闭,而是进入了TIME_WAIT状态。
- 客户端只有等待2MSL(Maximum Segment Life,报文段最大生存时间)才能完全关闭
- MSL:任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
- TCP 报文基于是 IP 协议的,而 IP 头中有一个
TTL
字段,是 IP 数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送ICMP
报文通知源主机。 - MSL 与 TTL 的区别:MSL 的单位是时间,而 TTL 是经过路由跳数。
- MSL 应该要大于等于 TTL 消耗为 0 的时间,以确保报文已被自然消亡。
- TCP 报文基于是 IP 协议的,而 IP 头中有一个
- MSL:任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
- 2MSL原因:
- 服务器端发送FIN给客户端的时候,服务端是不能当方面释放掉连接的,因为他不知道客户端收没收到自己的FIN,所以服务器必须要等待客户端发送的ACK过来,才能安全的释放TCP连接所占用的内存资源,端口号。所以服务器作为被动关闭的一方,是无需任何TIME_WAIT状态的。
- 客户端,他发送ACK给服务器端后,客户端并不知道服务端有没有收到这个报文
- 服务器没收到ACK,我就等着超时重传
- 服务器收到自己的ACK了,也不会发消息
- 客户端都必须要等带,而且要取最大值以应对最坏的情况发生
- 客户端发送ACK到服务器端的报文最大存活时间
- 服务器端从新发送FIN到客户端的报文最大存活时间即2MSL
- 没有TIME_WAIT或时间很短
- 报文具有相同的四元组的旧报文,可能会和新TCP连接的新报文起冲突
- 保证连接正确关闭
- TIME_WAIT过多
- 内存资源
- 端口的资源(服务器要考虑)
- 优化
- Linux内核中有一个默认值18000,当系统中的TIME_WAIT一旦超过这个值,系统就会将后面TIME_WAIT连接状态重置。
- 客户端只有等待2MSL(Maximum Segment Life,报文段最大生存时间)才能完全关闭
TCP连接中客户端故障
- 当在某个时间段内没有任何连接相关的活动,该机制就会每隔一个时间间隔发送一个探测报文,该报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前连接已经死亡,内核会通知应用程序然后中断连接 Linux中配置
- net.ipv4.tcp_keepalive_time=7200 //保活时间
- net.ipv4.tcp_keepalive_intvl=75 //每次检测间隔时间
- net.ipv4.tcp_keepalive_probes=9 //探测次数,9此后中断连接 情况
- 正常⼯作的
- 这样 TCP 保活时间会被重置,等待下⼀个 TCP 保活时间的到来。
- 崩溃并重启
- 对端是可以响应的,但由于没有该连接的有效信息,会产生⼀个 RST 报⽂,这样很快就会发现 TCP 连接重置
- 报文不可达
- 达到保活探测的最大次数之后会报告该连接已经死亡。
TCP粘包 原因
- TCP是面向字节流传输的,因此数据没有确切的边界,会出现前后两个数据包黏在一起的情况。
- 发送方:
- 为了减少网络中报文段的数量。上一个分组得到确认后才能发送下一个分组
- 收集多个小分组然后一起发送
- 接收方:
- 发送方和接收方各有两个缓冲空间,接收方收到数据后会将数据放到接收方的读缓存中。
- 如果读取的速度小于接收的速度,应用程序可能会读到多个首尾相连的包。 解决方案
- 发送方:
- 发送方:关闭nagle算法
- 接收方:交给应用层
- 应用层:粘包的原因是不确定消息的边界。
- 识别消息边界就行。加入特殊标志,头标志消息尾标志这样,或者加入每段消息的长度
TCP 协议保证可靠传输的手段
- 三次握手
- 校验和
- 流量控制
- TCP提供了一种机制让发送方根据接收方的实际接受能力控制发送的数据量。
- 接收方每次收到数据包,可以在发送确定报文的时候,同时告诉发送方自己的缓存区还剩余多少是空闲的,我们也把缓存区的剩余大小称之为接收窗口大小,用变量win来表示接收窗口的大小。
- 发送方收到之后,便会调整自己的发送速率,也就是调整自己发送窗口的大小,当发送方收到接收窗口的大小为0时,发送方就会停止发送数据,防止出现大量丢包情况的发生。
- 发送方停止发送数据,什么时候可以继续发送数据
- 接受窗口 win > 0 时,接收方发个通知报文去通知发送方
- 由于某种网络原因,这个报文丢失了
- 接收方发了通知报文后,继续等待发送方发送数据,而发送方则在等待接收方的通知报文,此时双方会陷入一种僵局死锁
- 由于某种网络原因,这个报文丢失了
- 当发送方收到接受窗口 win = 0 时,这时发送方停止发送报文,并且同时开启一个定时器,每隔一段时间就发个测试报文(窗口探测报文)去询问接收方,打听是否可以继续发送数据了
- 如果可以,接收方就告诉他此时接受窗口的大小;
- 如果接受窗口大小还是为0,则发送方再次刷新启动定时器。
- 接受窗口 win > 0 时,接收方发个通知报文去通知发送方
- 拥塞控制
原因
- 当网络环境出现拥塞的时候,可能会导致包的传输时延增加,丢包等问题,由于重传机制,会进入恶性循环 目的
-
如何知道拥塞,怎么避免拥塞 解决
- 定义了一个发送方维护的一个状态变量拥塞窗口,发送窗口=min(接收窗口,拥塞窗口)
- 拥塞窗口:定义了网络拥塞(只要发送方没有在规定时间内收到ACK确认报文,也就是发生了超时重传,就认为网络出现了拥塞)
- 拥塞控制方法
- 慢启动
- TCP在刚建立连接后,就会一点一点的提高发送数据包的速率,规则是:**当发送方每收到一个ACK确认报文,就会将拥塞窗口CWND的大小+1。
- CNWD也不是无限增长的,总有一个门限阈值,记作ssthresh。当cnwd小于这个阈值的时候就用慢启动算法,当大于等于这个阈值的时候就是用拥塞避免算法。
- 拥塞避免
- 当慢启动的cnwd窗口大于阈值,就会启动拥塞避免算法。
- 拥塞避免的规则是:每收到一个ACK时,cnwd增加1/cnwd,就变成了线性增长,在图上就是线性的。
- 最开始只有慢启动和拥塞避免两个算法,因为有时个别报文会在网络中丢失导致超时重传并误认为网络中发生拥塞
- 快重传
- 超时重传:
- ssthresh即阈值设为cnwd/2,cnwd=1,接着重新开始慢启动
- 快速重传算法:
- 要求接受方赶紧进行重传,不要等待计时器到时后再重传。
- 当接收方发现中丢包时,就会发送同一个ACK三次,发送端就需要快速重传,不必等待超时重传。
- 超时重传:
- 快速恢复
- 和快速重传机制一般都是同时使用的
- 门限阈值设置为cnwd/2
- 拥塞窗口cnwd=阈值ssthresh+3(3是因为收到三个重复确认表示有三个报文段离开网络,这三个报文在接收方缓存中而不再网络中)
- 重传丢失的数据包
- 如果收到了重复的ACK,则cnwd+1
- 如果收到新的ACK后,窗口值设为ssthresh,退出
- 慢启动
- 停止等待ARQ协议
- 每发完一个分组就停止发送,等待对方确认(回复ACK)。
- 如果过了一段时间(超时时间后),还是没有收到 ACK 确认,说明没有发送成功,需要重新发送,直到收到确认后再发下一个分组。
- 在停止等待协议中,若接收方收到重复分组,就丢弃该分组,但同时还要发送确认。
- 重传机制
- 超时重传
- 发送数据包在一定的时间周期内没有收到相应的ACK,等待一定的时间,超时之后就认为这个数据包丢失,就会重新发送。这个等待时间被称为RTO。
- 每一次开始发送一个TCP segment的时候,就启动重传定时器,定时器的时间一开始是一个预设的值(Linux 规定为1s)
- 随着通讯的变化以及时间的推移,这个定时器的溢出值是不断的在变化的,有相关算法计算RTO,如果在ACK收到之前,定时器到期,协议栈就会认为这个片段被丢失,重新传送数据。
- 需要保证能够在同一时刻有效的处理多个没有被确认的ACK
- 被发送的片段放在一个窗口中,等待被确认,没有确认不会从窗口中移走,定时器在重传时间到期内,每个片段的位置不变
- 只有等到ACK收到的时候,变成发送并ACK的片段,才会被从窗口中移走
- 如果定时器到期没有收到对应ACK, 就重传这个TCP segment
- 超时时间应该大于报文往返RTT的值。RTT:网络从一段传送到另一端所需的时间,RTT的值也经常波动
- 如果超时重发的数据又再次超时的时候,又需要重传,那么这个超时时间间隔加倍。
- 当两次超时时,就说明网络环境不行,不适合频繁反复发送数据。
- 发送数据包在一定的时间周期内没有收到相应的ACK,等待一定的时间,超时之后就认为这个数据包丢失,就会重新发送。这个等待时间被称为RTO。
- 快速重传
- 目的:针对超时重传中超时时期可能比较长的问题
- 当连续序列seq1-5中seq1发送后被接收方收到,接收方会返回一个ACK2和一个同步报文段。
- seq2没有到达接收方,则后面不论接收方收到了那个数据都是回ACk2,
- 当发送方连续收到了三个ACK2就表明seq2没有被接收方收到,就会重发。
- 但是问题在于通过重复确认机制,我们每次只能传送一个包
- 如果有多个包丢失,在传送过程中可能会造成timeout,造成带宽利用率下降
- 存在问题:
- 窗口容易卡住
- 即使窗口没有卡住,后面的所有都得验证,如果丢失很多,则需要一个一个传
- SACK
- 如果开启sack,每一个sack段记录的是已经收到的连续的包
- sack段与sack段之间断片的,也就是还没收到的(可能已经丢失,也可能是reorder)。
- 通过sack段便可以知道多个可能已经丢失的包,这样便可以一次性的重传,而不是一个一个重传,避免因等待时间长造成的timeout问题。
- 问题:
- 丢包意味着网络很可能已经拥塞,这时如果一次重传多个包,很可能会造成网络更加拥塞。
- D-SACK
- 超时重传
滑动窗口
目的
- 最开始TCP:每发送一个数据就要进行一次确认应答,当上一个数据包收到了应答,再发送下一个。这种模式就像是面对面聊天,效率比较低下。
- 滑动窗口机制是TCP的一种流量控制方法
- 该机制允许发送方在停止并等待确认前连续发送多个分组
- 而不必每发送一个分组就停下来等待确认,从而增加数据传输的速率提高应用的吞吐量。 实现
- 窗口大小就是无需等待确认应答,可以继续发送数据的最大值
- 窗口是操作系统开辟了一个缓存空间,发送方主机在确认应答返回之前在缓冲区中保留发送的数据,如果收到确认应答就可以抹去缓存的数据 构成
- #1已发送并且收到ACK
- #2已发送但未收到ACK
- #3未发送但总大小在接收方处理范围内
- #4未发送但总大小超过接收方处理范围
窗口大小控制
- 两个指针和一个位偏移量控制窗口大小
- 指向#2的第一个字节的序列号
- 指向#3的第一个字节的序列号
- 第三个是偏移量,是一个指针+窗口的大小(最终指向#4的第一个字节的序列号) 接收方窗口大小
- 滑动窗⼝并不是⼀成不变的。
- 当接收⽅的应⽤进程读取数据的速度⾮常快的话,这样的话接收窗⼝可以很快的就空缺出来。
- 新的接收窗⼝⼤⼩,是通过 TCP 报⽂中的 Windows 字段来告诉发送⽅。
- 这个传输过程是存在时延的,所以接收窗⼝和发送窗⼝是约等于的关系。
TCP内核参数优化
TCP抓包工具
TCP延迟确认与nagle算法
- 传输的数据很小,甚至小于头部20字节的时候,由于报文有效占比很低,有两种策略来减少小报文的传输:Nagle算法和延迟确认
- Nagle算法
- 避免发送小的数据包,要求TCP连接上最多只能有一个未被确认的小分组,在该分组的确认到达之前不能发送其他的小分组。
- 当发送缓冲中有多个这样的小分组的话,就收集这些小分组,组成一个大的tcp报文发送出去
- 如果一些小数据包交互的场景比如ssh这种,则需要关掉
- 延迟确认
- ACK确认报文没有携带数据,却有20字节的tcp头部和20字节的IP头部,因此传输的时候效率是很低的。
- 当有响应数据需要发送的时候,ack会随着响应数据一起发送
- 当没有响应数据时,ACK将会延迟一段时间,以等待是否有数据然后一起发送
- 如果在第二步延迟确认等待期间第二个数据报文有到达了,就会立刻发送ACK TCP四种定时器
- Nagle算法
- 重传计时器
- 报文段确认的等待时间。当TCP发送报文段时,就创建这个特定报文段的重传计时器,可能发生两种情况:若在计时器超时之前收到对报文段的确认,则撤销计时器;若在收到对特定报文段的确认之前计时器超时,则重传该报文,并把计时器复位;
- 坚持计时器
- 解决零窗口的死锁问题
- 保活计时器
- 服务器超过还没有收到来自客户的信息,就发送探测报文段,若发送了10个探测报文段(没75秒发送一个)还没收到响应,则终止连接。
- 时间等待计时器
- 在连接终止期使用,当TCP关闭连接时,并不认为这个连接就真正关闭了,在时间等待期间,连接还处于一种中间过度状态。这样就可以时重复的fin报文段在到达终点后被丢弃,这个计时器的值通常设置为一格报文段寿命期望值的两倍
网络层
IP地址和MAC地址缺一不可
- 网络层使用Ip协议将不同数据链路类型(以太网,3g,LAN)的数据报文统一成相同的形式在网络层中可以互相传播,达到任意具有IP地址的主机。
- 数据传输总要经过底层,经过线路传输。这时候就是数据链路层起到了作用,不同链路类型所使用的协议方案都不尽相同,但是在链路层不能使用IP地址了,这时候要找到相对应的主机我就需要MAC地址的作用。
- 只使用MAC进行通信,那么一个路由表就要维护差不多2的48次方数据,大约256TB的内存,这样存储和通信效率严重降低。
ICMP协议
- 确认网络是否正常以及遇到异常进行异常诊断的协议
- 应用
- 确认IP包是否成功送达目标地址。
- 返回在发送过程中IP包被废弃的真正原因。
- 改善网络设置
ARP协议
- 解决MAC和IP地址之间的问题。
- 确定了IP地址之后可以向对应IP地址的主机发送数据报
- 在底层数据要通过数据链路进行传输,必须知道每个IP地址对应的MAC地址才行。
RARP协议
- 将ARP反过来,从MAC地址定位到IP地址的协议。主要用于无法获取IP地址的设备,比如嵌入式设备。
DHCP协议
- 实现IP自动分配而生的协议,即插即用。
NAT协议
- 不要求为每一台设备分配一个固定的IP,而是在必要的时候为一定数量的设备分配唯一的IP(路由器)。
- 若是设备没有联网,只要保证IP地址在相应网络内部是唯一的即可。
- 出现了全局IP和私有IP的问题
- 全局IP要在整个互联网范围内唯一,但是私有地址不需要。
- NAT就是将私有地址在链接互联网时转换成全局IP是使用的技术。
- 但是实际上NAT本质上除了私有地址公有地址转换这一种用处之外最重要的就是将处于内网中的机器进行统一的管理和维护。
10.0.0.0-10.255.255.255 A类 172.16.0.0—172.31.255.255 B类 192.168.0.0-192.168.255.255 C类
数据链路层
集线器、网桥、交换机、路由器
- 集线器
- 一台电脑发出去的信号就可以被连接到hub上的其他电脑接收到,也就可以通信。一个口发送到的信号原封不动的发送到其他口,只是简单的转发,工作在物理层。
- 网桥
- 工作在数据链路层,因此跟其相关的就是mac地址。
- 只有目的地址mac被匹配了才会发送到出口。
- 交换机
- 把网络系统划分成为更多的物理网段,这样使得整个网络系统具有更高的带宽
- 路由器
- 工作在网络层,处理IP头部,查路由表,作三层转发。连接在路由器不同端口的设备属于不同的IP子网。
- 基于IP地址做转发。
ping
本质
- ping的本质就是ICMP协议
- ICMP又需要通过IP协议进行发送,发送的数据包有一定长度,
- 如果对方网络地址存在并且网络畅通无阻,就会收到同样大小的数据包,当然也有可能超时。
流程
- 主机A ping 主机B -> 构建ICMP数据包 -> 构建IP数据包 -> IP分组 -> 解析硬件地址封装成帧 -> 物理层 -> 网络层传输 -> 到达主机B -> 提取IP数据包交给IP层协议 -> 提取ICMP数据包信息,构建ICMP应答包 -> 发送给主机A
原理
- 功能:确认发送的IP包是否到达对方主机,报告发送过程中IP包被丢弃的原因
- 报文:IP头 + ICMP头
- IP头
- 版本
- 首部长度
- 服务类型
- 总长度
- 标志
- 片偏移
- TTL
- 协议(ICMP为1)
- 首尾校验
- source IP
- target IP
- ICMP 头
- 类型
- 查询报文类型主要由两个0和8,是回送消息。
- 回送消息主要用于相互通信的主机和路由器之间,判断所发送的数据包是否已经成功抵达对端,ping就是用这个消息实现的。
- 因此发送端会发送一个ICMP回送请求(类型 8)给对端主机,对端主机如果可以通信会发送ICMP回送响应(类型 0)
- 差错报文类型
- 3 目标不可达消息
- 类型字段是类型8,代码字段是具体不可到达的愿意
- 代码字段:0:匹配不到对方的网络号
- 代码字段:1:对端主机没有连接上网络
- 代码字段:2:找到对端主机,但是防火墙限制TCP协议访问
- 代码字段:3:找到对端主机,防火墙也没限制,但是没有进程监听相应端口
- 代码字段:4:发送端主机发送IP数据包的时候,将IP首部的分片禁止标志位设置为1,由于不进行分片,当途中路由器遇到超过MTU大小的数据包时就直接扔掉,然后报告发送端主机
- 4 原点抑制消息
- 当路由器向低速线路发送数据的时候,其发送队列的缓存变为0而无法发送出去,这个时候路由器向IP源地址即发送端发送一个ICMP原点抑制消息。收到该消息的主机端知道了某个线路发生了拥堵,从而增大IP包的传输间隔,减少网络拥堵。一般不被使用
- 5 重定向消息
- 如果路由器发送数据报不是从最优路径发送数据的话,会返回一个ICMP重定向消息给发送主机。这个消息中包含了最合适的路由信息和源数据。
- 11 超时消息
- TTL=0的时,路由器就会发送一个ICMP超时消息给发送端主机
- 3 目标不可达消息
- 代码
- 校验和
- 根据类型不同代码不同
- 类型
- IP头
ping发送过程
- 主机A ping 主机B
- A会构建一个ICMP回送请求消息数据报:
- 包括类型、序号、发送时间。回送消息请求的类型是8,序号的作用是为了区分连续ping的时候发出的多个数据包。因此每发送一个请求数据包,序号就会自动加1,同时为了计算往返时间RTT,还在报文的数据部分插入发送时间
- ICMP报文和目的地址一同交给IP层进行封装,构建一个IP数据包
- 为了在数据链路层进行传输,加入MAC头
- 在物理线路中传输
- 主机B收到数据包
- 首先检查MAC地址然后和本机MAC地址进行比对,如果相同则接受,不同则丢弃接收后提取IP数据包交给本机IP层协议栈处理,抽出IP后然后抽出ICMP检查
- 主机B会构建一个ICMP回送响应消息数据包,类型是0,序号为接受请求数据包中的序号,然后和上面一样的流程发送给主机A
- 在规定时间内如果收到,则减去该数据包最初的时间得到延迟
- 通过以上可以看出,ping命令使用的是ICMP协议中类型字段ECHO REQUEST(类型为 8 ) 和 ECHO REPLY (类型为 0)
应用:traceroute
- 故意设置特殊的 TTL,来追踪去往目的地时沿途经过的路由器。
- 它的原理就是利用 IP 包的生存期限 从 1 开始按照顺序递增的同时发送 UDP 包,强制接收 ICMP 超时消息的一种方法。比如,将 TTL 设置 为 1,则遇到第一个路由器,就牺牲了,接着返回 ICMP 差错报文网络包,类型是时间超时。
- 接下来将 TTL 设置为 2,第一个路由器过了,遇到第二个路由器也牺牲了,也同时返回了 ICMP 差错报文数据包,如此往复,直到到达目的主机。这样的过程,traceroute 就可以拿到了所有的路由器 IP。
- 填入一个不可能的端口号值作为 UDP 目标端口号(大于 3000 )当目的主机,收到 UDP 包后,会返回 ICMP 差错报文消息,但这个差错报文消息的类型是「端口不可达」
- 故意设置不分片,从而确定路径的 MTU
- 将 IP 包首部的分片禁止标志位设置为 1。根据这个标志位,途中的路由器不会对大数据包进行分片,而是将包丢弃。随后,通过一个 ICMP 的不可达消息将数据链路上 MTU 的值一起给发送主机,不可达消息的类型为「需要进行分片但设置了不分片位」。发送主机端每次收到 ICMP 差错报文时就减少包的大小,以此来定位一个合适的 MTU 值,以便能到达目标主机。
信道争用
- 共享介质性网络
- 采用半双工通信
- 非共享介质网络
- 计算机之间不互相链接,而是都与交换机直接相连
- CSMA/CD(载波侦听多路访问/冲突检测)
- 发送数据前,先侦听信道是否空闲,若空闲,则立即发送数据。
- 若信道忙碌,则等待一段时间至信道中的信息传输结束后再发送数据
- 若在上一段信息发送结束后,同时有两个或两个以上的节点都提出发送请求,则判定为冲突
- 侦听到冲突,则立即停止发送数据,等待一段随机时间,再重新尝试。
- 总结:先听后发,边发边听,冲突停发,随机延迟后重发。