面试基础知识(3)—— 计算机网络与数据结构基础考点
计算机网络基础
OSI和TCP/IP网络分层模型
相关问题:
1)OSI七层模型是什么?每一层的作用是什么?
2)TCP/IP四层模型是什么?五层模型?
3)为什么网络要分层?
4)数据在各层之间的传递过程?
OSI七层模型
OSI七层模型是国际标准化组织提出一个网络分层模型。
- 物理层:利用传输介质为数据链路层提供支持,实现相邻计算机节点之间比特流的透明传送
- 数据链路层:管理相邻节点之间的数据通信
- 网络层:IP编址,路由和寻址(决定数据在网络的游走路径)
- 传输层:为两台主机进程之间的通信提供通用的数据传输服务
- 会话层:管理(建立、维护、重连)应用程序之间的会话
- 表示层:数据处理(编解码、加密解密、压缩解压缩)
- 应用层:为计算机用户提供服务
说明:
- 在四层,既传输层数据被称作段(Segments);
- 三层网络层数据被称做包(Packages);
- 二层数据链路层时数据被称为帧(Frames);
- 一层物理层时数据被称为比特流(Bits)。
**分层的好处:**每层是独立的;灵活性好;结构上可以分隔开;易于实现和维护;促进标准化工作;
OSI 的七层体系结构概念清楚,理论也很完整,但是它比较复杂而且不实用,而且有些功能在多个层中重复出现。
七层体系的不足:
- OSI 的专家缺乏实际经验,他们在完成 OSI 标准时缺乏商业驱动力
- OSI 的协议实现起来过分复杂,而且运行效率很低
- OSI 制定标准的周期太长,因而使得按 OSI 标准生产的设备无法及时进入市场(20 世纪 90 年代初期,虽然整套的 OSI 国际标准都已经制定出来,但基于 TCP/IP 的互联网已经抢先在全球相当大的范围成功运行了)
- OSI 的层次划分不太合理,有些功能在多个层次中重复出现。
TCP/IP四层模型
TCP/IP 四层模型 是目前被广泛采用的一种模型,我们可以将 TCP / IP 模型看作是 OSI 七层模型的精简版本,由以下 4 层组成:应用层、传输层、网络层、网络接口层。
五层模型
对于同⼀台设备上的进程间通信,有很多种⽅式,⽐如有管道、消息队列、共享内存、信号等⽅式,⽽对于不同设备上的进程间通信,就需要⽹络通信,⽽设备是多样性的,所以要兼容多种多样的设备,就协商出了⼀套通⽤的⽹络协议。
这个网络协议是分层的,每一层都有各自的作用和职责。
五层模型:
1)应用层(Application Layer)
为应用程序提供交互服务。在互联网中的应用层协议很多,如域名系统DNS、HTTP协议、SMTP协议等。
应用层只需要专注于为用户提供应用功能,不去关心数据如何传输。而且应用层是工作在操作系统的用户态,传输层及其以下工作在内核态。
应用层协议:
- HTTP 协议(超文本传输协议,网页浏览常用的协议)
- DHCP 协议(动态主机配置)
- DNS 系统原理(域名系统)
- FTP 协议(文件传输协议)
- Telnet协议(远程登陆协议)
- 电子邮件协议等(SMTP、POP3、IMAP)
2)传输层(Transport Layer)
传输层的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务。 应用进程利用该服务传送应用层报文。
在传输层主要使用以下两种协议:
- 传输控制协议 TCP(Transmisson Control Protocol):提供 面向连接 的,可靠的 数据传输服务。大部分应用使用的正是TCP协议,比如HTTP协议。TCP相比 UDP多了很多特性,比如流量控制、超时重传、拥塞控制等,这些都是为了保证数据包能可靠地传输给对方。
- 用户数据协议 UDP(User Datagram Protocol):提供 无连接 的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。只负责发送数据包,不保证数据包是否能抵达对方,但它实时性相对更好,传输效率也高。当然,UDP也可以实现可靠传输,把TCP的特性在应用层上实现就可以,不过要实现一个商用的可靠UDP传输协议,也不是一件简单的事情。
应用需要传输的数据可能会非常大,如果直接传输就不好控制,因此当传输层的数据包大小超过 MSS (TCP最大报文段长度),就要将数据包分块,这样即使中途有一个分块丢失或损坏了,只需要重新发送这一个分块,而不用重新发送整个数据包。在TCP协议中,我们把每个分块称为一个TCP 段(TCP Segment)。
当设备作为接收方时,传输层则要负责把数据包传给应用,但是一台设备上可能会有很多应用在接收或者传输数据,因此需要用一个编号将应用区分开来,,这个编号就是端口。
比如80端口通常是Web服务器用的,22端口通常是远程登录服务器用的。而对于浏览器(客户端)中的每个标签栏都是一个独立的进程,操作系统会为这些进程分配临时的端口号。
由于传输层的报文中会携带端口号,因此接收方可以识别出该报文是发送给哪个应用。
3)网络层(Internet Layer)
网络层负责为分组交换网上的不同主机提供通信服务。 在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP/IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报,简称数据报。
网络层的还有一个任务就是选择合适的路由,使源主机运输层所传下来的分组,能通过网络层中的路由器找到目的主机。
网络层最常使用的是IP协议,IP协议会将传输层的报文作为数据部分,再加上IP包头组装成IP报文,如果IP报文大小超过MTU(以太网中一般为1500字节)就会再次进行分片,得到一个即将发送到网络的IP报文。
网络层使用IP地址给设备进行编号,用来找到网络中的设备。对于IPv4协议,IP地址共32位,分成了四段,每段是8位。将IP地址分成两部分:
- 一个是网络号,负责标识该IP地址是属于哪个子网的;
- 一个是主机号,负责标识同一子网下的不同主机;
这需要配合子网掩码才能算出IP地址的网络号和主机号。在寻址的过程中,先匹配到相同的网络号,才会去找对应的主机。
除了寻址能力,IP协议还有另一个重要的能力就是路由。实际场景中,两台设备并不是用一条网线连接起来的,而是通过很多网关、路由器、交换机等众多网络设备连接起来的,那么就会形成很多条网络的路径,因此当数据包到达一个网络节点,就需要通过算法决定下一步走哪条路径。
所以,IP协议的寻址作用是告诉我们去往下一个目的地该朝哪个方向走,路由则是根据「下一个目的地」选择路径。
网络层常见协议:
- IP网际协议
- ARP协议(地址解析协议):解决的是网络层地址和链路层地址之间的转换问题。
- ICMP协议(网际控制报文协议):用于发送控制消息
- NAT网络地址转换协议:应用于内部网到外部网的地址转换过程中。
- RIP协议、OSPF协议、BGP协议:路由选择协议
- ...
4)数据链路层(Data Link Layer)
数据链路层的作用是将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。
每一台设备的网卡都会有一个MAC地址,它就是用来唯一标识设备的。路由器计算出了下一个目的地IP地址,再通过ARP协议找到该目的地的MAC地址,这样就知道这个IP地址是哪个设备的了。
5)物理层(Physical Layer)
物理层的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异。
数据在各层之间的传递过程
在向下的过程中,需要添加下层协议所需要的首部或者尾部,而在向上的过程中不断拆开首部和尾部。
路由器只有下面三层协议,因为路由器位于网络核心中,不需要为进程或者应用程序提供服务,因此也就不需要传输层和应用层。
应用层
应用层常见协议
SMTP:简单邮件传输协议
电子邮件的发送过程?
比如我的邮箱是“dabai@cszhinan.com”,我要向“xiaoma@qq.com”发送邮件,整个过程可以简单分为下面几步:
- 通过 SMTP 协议,我将我写好的邮件交给163邮箱服务器(邮局)。
- 163邮箱服务器发现我发送的邮箱是qq邮箱,然后它使用 SMTP协议将我的邮件转发到 qq邮箱服务器。
- qq邮箱服务器接收邮件之后就通知邮箱为“xiaoma@qq.com”的用户来收邮件,然后用户就通过 POP3/IMAP 协议将邮件取出。
如何判断邮箱是真正存在的?
很多场景(比如邮件营销)下面我们需要判断我们要发送的邮箱地址是否真的存在,这个时候我们可以利用 SMTP 协议来检测:
- 查找邮箱域名对应的 SMTP 服务器地址
- 尝试与服务器建立连接
- 连接成功后尝试向需要验证的邮箱发送邮件
- 根据返回结果判定邮箱地址的真实性
FTP文件传输协议
FTP 的独特的优势同时也是与其它客户服务器程序最大的不同点就在于它在两台通信的主机之间使用了两条 TCP 连接(其它客户服务器应用程序一般只有一条 TCP 连接):
- 控制连接:用于传送控制信息(命令和响应)
- 数据连接:用于数据传送;
这种将命令和数据分开传送的思想大大提高了 FTP 的效率。
总结
- POP3
- 因特网电子邮件的第一个离线协议标准(联想笔试)。
协议 | 名称 | 默认端口 | 底层协议 | 补充 |
---|---|---|---|---|
HTTP | 超文本传输协议 | 80 | TCP | |
HTTPS | 超文本传输安全协议 | 443 | TCP | |
SSH | 安全的网络传输协议 | 22 | TCP | Telnet 和 SSH 之间的主要区别在于 SSH 协议会对传输的数据进行加密保证数据安全性。 |
Telnet | 远程登录协议 | 23 | TCP | Telnet 协议的最大缺点之一是所有数据(包括用户名和密码)均以明文形式发送 |
FTP | 文件传输协议 | 20传输和21连接 | TCP | 1)屏蔽操作系统和文件存储方式。 |
SMTP | 简单邮件传输协议(发送用) | 25 | TCP | |
POP3 | 邮局协议(接收用) | 110 | TCP | |
IMAP | 互联网邮件访问协议(接收用) | |||
DNS | 域名解析服务 | 53 | 服务器间进行域传输的时候用TCP 客户端查询DNS服务器时用 UDP | |
DHCP | 动态主机配置协议 | 采用67(DHCP服务器端)和68(DHCP客户端)两个端口号 | UDP | 指的是由服务器控制一段IP地址范围,给用户提供了即插即用的联网方式,用户不需要再手动配置 IP 地址等信息。该协议自动为用户分配TCP/IP参数信息,如:IP地址,子网掩码,网关等信息。 |
SNMP | 简单网络管理协议 | 161 | UDP | |
TFTP | 简单文件传输协议 | 69 | UDP |
HTTP
HTTP是什么
HTTP是超文本传输协议,也就是HyperText Transfer Protocal。HTTP是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。
HTTP常见字段
1)Host字段
客户端发送请求时,用来指定服务器的域名。有了Host字段,就可以将请求发往「同一台」服务器上的不同网站。
2)Content-Length字段
服务器在返回数据时,会有Content-Length字段,表明本次回应的数据长度。
3)Connection字段
Connection字段最常用于客户端要求服务器使用TCP持久连接,以便其他请求复用。HTTP/1.1版本的默认连接都是持久连接,但为了兼容老版本的HTTP,需要指定Connection首部字段的值为Keep-Alive 。除非请求中写明 Connection: close,那么浏览器和服务器之间是会维持一段时间的 TCP 连接,不会一个请求结束就断掉。
一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段。
4)Content-Type字段
Content-Type字段用于服务器回应时,告诉客户端,本次数据是什么格式。客户端请求的时候,可以使用Accept字段声明自己可以接受哪些数据格式。
5)Content-Encoding字段
Content-Encoding字段说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式。客户端在请求时,用 Accept-Encoding字段说明自己可以接受哪些压缩方法。
HTTP报文格式
HTTP请求由请求行、请求头部、空行和请求体四个部分组成。
- 请求行Request Line:包括请求方法,访问的资源URL,使用的HTTP版本。GET和POST是最常见的HTTP方法,除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE。
- 请求头Request Headers:格式为“属性名:属性值”,服务端根据请求头获取客户端的信息,主要有cookie、host、connection、accept-language、accept-encoding、user-agent。
- 请求体Request Body:用户的请求数据如用户名,密码等。
HTTP响应也由四个部分组成,分别是: 状态行、响应头、空行和响应体。
- 状态行:协议版本,状态码及状态描述。
- 响应头:响应头字段主要有connection、content-type、content-encoding、content-length、set-cookie、Last-Modified,、Cache-Control、Expires。
- 响应体:服务器返回给客户端的内容。
HTTP请求方式
客户端发送的请求报文第一行为请求行,包含了方法字段。
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
序 号 | 方法 | 描述 |
---|---|---|
1 | GET | 请求指定的页面信息,并返回实体主体。 |
2 | HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
3 | POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。 |
4 | PUT | 从客户端向服务器传送的数据取代指定的文档的内容。即更改资源 |
5 | DELETE | 请求服务器删除指定的页面。 |
6 | CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 |
7 | OPTIONS | 允许客户端查看服务器的性能。 |
8 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
9 | PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 。 |
HTTP基于TCP还是UDP
HTTP 协议是基于 TCP 协议的,所以发送 HTTP 请求之前首先要建立 TCP 连接也就是要经历 3 次握手。
HTTP 协议是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范。
从输入URL到页面展示到底发生了什么?(一次完整的HTTP请求过程包含什么内容)
类似问题:打开一个网页,整个过程中使用哪些协议?
- 根据域名,进行DNS域名解析;
- 拿到解析的IP地址,建立TCP连接;
- 向IP地址,发送HTTP请求;
- 服务器处理请求;
- 返回响应结果;
- 关闭TCP连接;
- 浏览器解析HTML代码,并请求html代码中的资源(如js、css、图片等);
- 浏览器布局渲染;
另外一种说法:
浏览器解析URL对应的IP地址
DNS解析过程,浏览器缓存—>操作系统缓存—>本地DNS—>根据转发模式选择迭代还是递归查询
浏览器向服务器发送一个HTTP请求报文
传输层上建立TCP连接,网络层用到了IP协议(负责在网络层传输数据),还会用到RIP或者OSPF进行路由选择,然后用ARP协议解析IP地址对应的MAC地址,使得数据能够在数据链路层上进行传输(不应该是最后到物理层传输吗)
HTTP请求方法有哪些(post/get/head/put/delete)
服务器请求处理并返回一个HTTP响应报文
HTTP响应报文的结构,状态码
服务器返回一个HTML响应,浏览器收到HTML响应并渲染界面
使用哪些协议:DNS协议、HTTP协议、TCP协议、UDP协议(DNS基于UDP协议)、IP协议、ARP协议、ICMP协议(在网络层如果出现差错会调用ICMP协议)、路由选择协议
输入一个URL之后,浏览器就会对这个URL进行解析,就需要使用DNS域名解析服务,然后DNS域名解析有两种方法,递归和迭代;完成DNS域名解析之后,获得IP地址,这个时候发起HTTP传输,在传输之前需要建立一个TCP连接,然后数据报到达网络层,需要使用IP协议进行寻址和路由,在这个过程需要找到相应的MAC地址就需要使用ARP地址解析协议,如果网络层出现问题会调用ICMP协议。
HTTP状态码有哪些?
HTTP 状态码用于描述 HTTP 请求的结果,比如2xx 就代表请求被成功处理。
1xx:提示信息,表示目前是协议处理的中间状态,还需要后续的操作;
- 1xx类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
2xx:成功,报文已经收到并被正确处理;
- 2xx类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。
- 200 OK:最常见的成功状态码,表示请求成功。一般用于GET与POST请求
- 201 Created:已创建。成功请求并创建了新的资源
- 202 Accepted:已接受。已经接受请求,但未处理完成
- 204 No Content:无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
- 206 Partial Content:部分内容。服务器成功处理了部分GET请求。
3xx:重定向,资源位置发生变动。
- 3xx类状态码表示客户端请求的资源发送了变动,需要客户端用新的URL重新发送请求获取资源,也就是重定向。
- 301 Moved Permanently: 资源被永久重定向了。服务器返回此响应时,会自动将请求者转到新位置。
- 302 Found:资源被临时重定向了。比如你的网站的某些资源被暂时转移到另外一个网址。
- 304 Not Modified:不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,用于缓存控制。
4xx:
- 4xx类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。
- 400 Bad Request:发送的HTTP请求存在语法问题。比如请求参数不合法、请求方法错误。
- 403 Forbidden:直接拒绝HTTP请求,不处理。一般用来针对非法请求。
- 404 Not Found:表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。
5xx
- 5xx类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。
- 500 Internal Server Error:服务器内部错误,无法完成请求。
- 501 Not Implemented:服务器不支持请求的功能,无法完成请求
- 502 Bad Gateway:作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
- 503 Service Unavailable:由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
HTTP协议的特点,优点与缺点
特点:
- 无状态:对于客户端每次发送的请求,服务器都认为是一个新的请求,上一次会话和下一次会话之间没有联系;
- 支持客户端/服务器模式。
优点:
- 简单:HTTP基本的报文格式就是 header + body,头部信息也是key-value简单文本形式,易于理解。
- 灵活和易于扩展:HTTP协议里面各种请求方式、URI/URL、状态码、头字段等每个组成要求没有固定,允许开发人员自定义和扩充。HTTP由于工作在应用层(OSI第七层),它下层可以随意变化。
- 应用广泛和跨平台
缺点:
无状态双刃剑:
- 无状态好处:服务器不会记忆HTTP的状态,所以不需要额外的资源记录状态信息,这能减轻服务器的负担,能够把更多的CPU和内存用来对外提供服务。
- 坏处:因为服务器没有记忆能力,它在完成有关联性的操作时会非常麻烦。例如登录-→添加购物车-→>下单->结算->支付,这系列操作都要知道用户的身份才行。但服务器不知道这些请求是有关联的,每次都要问一遍身份信息。
对于无状态的问题有很多解决方法,其中比较简单的方式用Cookie技术。
明文传输双刃剑:
- 好处:明文意味着在传输过程中的信息,是可方便阅读的。
- 坏处:隐私泄露问题,隐私很容易被窃取。
不安全
- 通信使用明文(不加密),内容可能被窃听;
- 不验证通信方身份,可能遭遇伪装;
- 无法验证报文完整性,可能已被篡改;
可以用 HTTPS的方式解决,也就是通过引入SSL/TLS层解决不安全的问题;
HTTP长连接和短连接以及各自的应用场景
HTTP1.0默认使用短连接。浏览器和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。
HTTP1.1起,默认使用长连接,要使用长连接,客户端和服务器的HTTP首部的Connection都要设置为keep-alive,才能支持长连接。
HTTP长连接,指的是 复用TCP连接。多个HTTP请求可以复用同一个TCP连接,这就节省了TCP连接建立和断开的消耗。
- 长连接多用于操作频繁、点对点的通讯,并且连接数不能太多的情况;
- 短连接适用于并发量大、每个用户无需频繁操作的情况。
HTTP/1.1性能
HTP协议是基于TCP/IP,并且使用了「请求-应答」的通信模式。
1)长连接
HTTP/1.1 提出了长连接的通信方式,也叫持久连接。这种方式的好处在于减少了TCP连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。
持久连接的特点是,只要任意一端没有明确提出断开连接,则保持TCP连接状态。
2)管道(pipeline)网络传输
HTTP/1.1可在同一个TCP连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发出第二个请求,减少整体的响应时间。
举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求。
但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为「队头堵塞」。
3)队头阻塞
当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一同被阻塞了,会导致客户端一直请求不到数据,这也就是「队头阻塞」。
HTTP1.1和HTTP2.0的区别
HTTP2.0相比HTTP1.1支持的特性:
- 新的二进制格式:HTTP1.1 基于文本格式传输数据;HTTP2.0采用二进制格式传输数据,解析更高效。
- 多路复用:在一个连接里,允许同时发送多个请求或响应,并且这些请求或响应能够并行的传输而不被阻塞,避免 HTTP1.1 出现的”队头堵塞”问题。
- 头部压缩,HTTP1.1的header带有大量信息,而且每次都要重复发送;HTTP2.0 把header从数据中分离,并封装成头帧和数据帧,使用特定算法压缩头帧,有效减少头信息大小。并且HTTP2.0在客户端和服务器端记录了之前发送的键值对,对于相同的数据,不会重复发送。比如请求a发送了所有的头信息字段,请求b则只需要发送差异数据,这样可以减少冗余数据,降低开销。
- 服务端推送:HTTP2.0允许服务器向客户端推送资源,无需客户端发送请求到服务器获取。
HTTPS是如何保证数据传输的安全,整体的流程是什么?(SSL是怎么工作保证安全的)
(1)客户端向服务器端发起SSL连接请求; (2) 服务器把公钥发送给客户端,并且服务器端保存着唯一的私钥 (3)客户端用公钥对双方通信的对称秘钥进行加密,并发送给服务器端 (4)服务器利用自己唯一的私钥对客户端发来的对称秘钥进行解密, (5)进行数据传输,服务器和客户端双方用公有的相同的对称秘钥对数据进行加密解密,可以保证在数据收发过程中的安全,即是第三方获得数据包,也无法对其进行加密,解密和篡改。
服务器第一次传给客户端的公钥其实是CA对网站信息进行加密的数字证书。
因为数字签名、摘要是证书防伪非常关键的武器。 “摘要”就是对传输的内容,通过hash算法计算出一段固定长度的串。然后,通过发送方的私钥对这段摘要进行加密,加密后得到的结果就是“数字签名”
SSL/TLS协议的基本思路是采用公钥加密法,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。
补充:SSL/TLS的四次握手,目前网上的主流答案都在重复阮一峰老师的博客,属于TLS 1.0版本的答案,使用RSA密钥交换算法。但是现在TLS 1.2已经成为主流,使用ECDHE算法,如果面试可以说出这个版本的答案,应该会更好。
一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)?
HTTP/1.1 存在一个问题,单个 TCP 连接在同一时刻只能处理一个请求,意思是说:两个请求的生命周期不能重叠,任意两个 HTTP 请求从开始到结束的时间在同一个 TCP 连接里不能重叠。
在 HTTP/1.1 存在 Pipelining 技术可以完成这个多个请求同时发送,但是由于浏览器默认关闭,所以可以认为这是不可行的。在 HTTP2 中由于 Multiplexing 特点的存在,多个 HTTP 请求可以在同一个 TCP 连接中并行进行。
那么在 HTTP/1.1 时代,浏览器是如何提高页面加载效率的呢?主要有下面两点:
- 维持和服务器已经建立的 TCP 连接,在同一连接上顺序处理多个请求。
- 和服务器建立多个 TCP 连接。
浏览器对同一 Host 建立 TCP 连接的数量有没有限制?
假设我们还处在 HTTP/1.1 时代,那个时候没有多路传输,当浏览器拿到一个有几十张图片的网页该怎么办呢?肯定不能只开一个 TCP 连接顺序下载,那样用户肯定等的很难受,但是如果每个图片都开一个 TCP 连接发 HTTP 请求,那电脑或者服务器都可能受不了,要是有 1000 张图片的话总不能开 1000 个TCP 连接吧,你的电脑同意 NAT 也不一定会同意。
有。Chrome 最多允许对同一个 Host 建立六个 TCP 连接。不同的浏览器有一些区别。
如果图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。不过也未必会所有挂在这个域名的资源都会使用一个 TCP 连接去获取,但是可以确定的是 Multiplexing 很可能会被用到。
如果发现用不了 HTTP2 呢?或者用不了 HTTPS(现实中的 HTTP2 都是在 HTTPS 上实现的,所以也就是只能使用 HTTP/1.1)。那浏览器就会在一个 HOST 上建立多个 TCP 连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求,如果所有的连接都正在发送请求呢?那其他的请求就只能等等了。
HTTP和HTTPS的区别
HTTP vs HTTPS(应用层) | JavaGuide
区别:
- 端口号 :HTTP 默认是 80,HTTPS 默认是 443。
- URL 前缀 :HTTP 的 URL 前缀是
http://
,HTTPS 的 URL 前缀是https://
。 - HTTPS协议需要到CA机构申请证书,一般需要一定的费用。
- HTTPS比HTTP需要耗费更多的资源,响应速度也更慢;
- HTTPS更安全以及所在层次不同
- HTTP是超文本传输协议,不提供身份认证和数据加密,信息是明文传输,通过抓包工具可以分析其信息内容;
- HTTPS协议是由SSL+HTTP协议构建的可进行加密传输和身份认证的网络协议。以对称加密的方式为传输的数据进行加密,用数字证书的方式提供服务器端的身份认证(对称加密的密钥用服务器方的证书进行了非对称加密),更为安全;
- HTTP运行在TCP协议之上;HTTPS运行在SSL/TLS协议之上,SSL/TLS运行在TCP协议之上。所以HTTP三次握手之后便可进行HTTP的报文传输。而HTTPS在TCP三次握手之后,还需进行 SSL/TLS的握手过程,才可进入加密报文传输。
HTTPS解决了HTTP哪些问题,怎么解决
HTTPS在HTTP与TCP层之间加入了SSL/TLS协议,解决HTTP中存在的以下问题:
- 使用明文进行通信,内容可能会被窃听(窃听风险);
- 不验证通信方的身份,通信方的身份有可能遭遇伪装(冒充风险);
- 无法证明报文的完整性,报文有可能遭篡改(篡改风险)
1)混合加密:保证消息的机密性,解决窃听风险
HTTPS采用的是对称加密和非对称加密结合的**「混合加密」**方式:
- 在通信建立前采用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密。
- 在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。
采用「混合加密」的方式的原因:
- 对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换。
- 非对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢。
2)摘要算法:校验数据完整性,解决被篡改风险;
客户端在发送明文之前会通过摘要算法算出明文的「指纹」,发送的时候把「指纹+明文」一同加密成密文后,发送给服务器,服务器解密后,用相同的摘要算法算出发送过来的明文,通过比较客户端携带的「指纹」和当前算出的「指纹」做比较,若「指纹」相同,说明数据是完整的。
3)数字证书:将服务器公钥放入到数字证书中,解决了冒充的风险。
客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。这就存在些问题,如何保证公钥不被篡改和信任度?
所以这里就需要借助第三方权威机构CA(数字证书认证机构),将服务器公钥放在数字证书(由数字证书认证机构CA颁发)中,只要证书是可信的,公钥就是可信的。
HTTPS是如何建立连接的,其间交互了什么?
SSL/TLS的握手阶段涉及四次通信。
确保传输安全过程(其实就是rsa原理):
- Client给出SSL/TLS协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。
- Server确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。
- Client确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给Server。
- Server使用自己的私钥,获取Client发来的随机数(Premaster secret)。
- Client和Server根据约定的加密方法,使用前面的三个随机数,生成**”对话密钥”**(session key),用来加密接下来的整个对话过程。
对称密钥和非对称密钥优缺点
对称密钥加密:加解密使用同一密钥。
- 优点:运算速度快
- 缺点:无法安全将密钥传输给通信方;
- 常用算法:DES,3DES,IDEA,CR4,CR5,CR6,AES
非对称密钥加密:加解密使用不同密钥;公密所有人都可以获得,通信发送方获得接收方的公密之后,就可以使用公开密钥进行加密,接收方收到通信内容后使用私有密钥解密。非对称密钥除了用来加密,还可以用来进行签名。
- 优点:可以更安全地将公开密钥传输给通信发送方;
- 缺点:运算速度慢。
- 常用算法:RSA,ECC,DSA
什么是SSL/TLS
**SSL是传输层协议。**SSL代表安全套接字层。它是一种用于加密和验证应用程序(如浏览器)和Web服务器之间发送的数据的协议。SSL/TLS协议作用:认证用户和服务,加密数据,维护数据的完整性的应用层协议。SSL和TLS(标准化名称)是同一个东西的不同阶段。
HTTP协议与TCP的区别和联系
联系:Http协议是建立在TCP协议基础之上的,当浏览器需要从服务器获取网页数据的时候,会发出一次Http请求。Http会通过TCP建立起一个到服务器的连接通道,当本次请求需要的数据传输完毕后,Http会立即将TCP连接断开,这个过程是很短的。
区别:HTTP和TCP位于不同的网络分层。TCP是传输层的协议,定义的是数据传输和连接的规范,而HTTP是应用层的,定义的是数据的内容的规范。 建立一个TCP请求需要进行三次握手,而由于http是建立在tcp连接之上的,建立一个http请求通常包含请求和响应两个步骤。
HTTP协议和Socket区别,哪个协议更高效?
(1)很多情况下,需要服务端主动向客户推送数据,保持客户端与服务端数据的实时与同步。但HTTP无法满足这一需求,Socket可以满足。
原因如下:
HTTP连接使用“请求—响应”方式。不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务端才能回复数据。
若建立的是HTTP连接,则服务端需等到客户端发送一次请求后,才能将数据传回给客户端。
此时若双方建立的是Socket连接,服务器就可直接将数据传送给客户端;
Socket连接一旦建立,通信双方即可相互发送数据内容,直到双方连接断开。
(2)创建Socket连接时,Socket可支持不同的传输层协议(TCP或UDP)。而HTTP只能基于TCP。
- Socket不仅能走TCP,还能走UDP。当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。
- 同HTTP不同的是,HTTP只能基于TCP。
(3)Socket效率高,至少不用解析HTTP报文头部的一些字段。
HTTP 1.0 和HTTP1.1的区别
HTTP/1.1相比HTTP/1.0性能上的改进:
状态响应码: HTTP/1.0仅定义了16种状态码,HTTP/1.1中新加入了大量的状态码。
连接方式:HTTP/1.0 默认使用短连接,为了解决 HTTP/1.0 存在的资源浪费的问题, HTTP/1.1 优化为默认长连接模式 。HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。
实现长连接需要客户端和服务端都支持长连接。
支持管道((pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。
Host头处理:域名系统(DNS)允许多个主机名绑定到同一个IP地址上,但是HTTP/1.0并没有考虑这个问题,假设我们有一个资源URL是http://example1.org/home.html,HTTP/1.0的请求报文中,将会请求的是
GET /home.html HTTP/1.0
.也就是不会加入主机名。这样的报文送到服务器端,服务器是理解不了客户端想请求的真正网址。因此,HTTP/1.1在请求头中加入了
Host
字段。加入Host
字段的报文头部将会是:GET /home.html HTTP/1.1 Host: example1.org
这样,服务器端就可以确定客户端想要请求的真正的网址了。
但HTTP/1.1还是有性能瓶颈:
- 请求/响应头部(Header)未经压缩就发送,首部信息越多延迟越大。只能压缩Body的部分;
- 发送冗长的首部。每次互相发送相同的首部造成的浪费较多;
- 服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞;没有请求优先级控制;
- 请求只能从客户端开始,服务器只能被动响应。
针对HTTP/1.1的性能瓶颈,HTTP/2做了什么优化?
HTTP/2协议是基于HTTPS的,所以HTTP/2的安全性是有保障的。
HTTP/2相比HTTP/1.1性能上的改进:
1)头部压缩
HTTP/2会压缩头(Header),如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。
这就是所谓的HPACK 算法︰在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
2)二进制格式
HTTP/2不再像HTTP/1.1里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧和数据帧。
受到报文后,无需将明文的报文转成二进制,而是直接解析二进制报文,从而增加数据传输的效率。
3)数据流
HTTP/2的数据包不是按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。
每个请求或回应的所有数据包,称为一个数据流(Stream )。每个数据流都标记着一个独一无二的编号,其中规定客户端发出的数据流编号为奇数,服务器发出的数据流编号为偶数
客户端还可以指定数据流的优先级。优先级高的请求,服务器就先响应该请求。
4)多路复用
HTTP/2是可以在一个连接中并发多个请求或回应,而不用按照顺序一一对应。
移除了HTTP/1.1 中的串行请求,不需要排队等待,也就不会再出现「队头阻塞」问题,降低了延迟,大幅度提高了连接的利用率。
举例来说,在一个TCP连接里,服务器收到了客户端A和B的两个请求,如果发现A处理过程非常耗时,于是就回应A请求已经处理好的部分,接着回应B请求,完成后,再回应A请求剩下的部分。
5)服务器推送
HTTP/2还在一定程度上改善了传统的「请求–应答」工作模式,服务不再是被动地响应,也可以主动向客户端发送消息。
举例来说,在浏览器刚请求HTML的时候,就提前把可能会用到的JS、CSS 文件等静态资源主动发给客户端,减少延时的等待,也就是服务器推送(Server Push,也叫Cache Push)。
HTTP是不保存状态的协议,如何保存用户状态?
HTTP 是一种不保存状态,即无状态(stateless)协议。也就是说 HTTP 协议自身不对请求和响应之间的通信状态进行保存。如何保存用户状态呢?Session 机制就是为了解决这个问题,Session 的主要作用就是通过服务端记录用户的状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了(一般情况下,服务器会在一定时间内保存这个 Session,过了时间限制,就会销毁这个 Session)。
在服务端保存 Session 的方法很多,最常用的就是内存和数据库(比如使用内存数据库 redis 保存)。既然 Session 存放在服务器端,那么我们如何实现 Session 跟踪呢?大部分情况下,我们都是通过在 Cookie 中附加一个 Session ID 来方式来跟踪。
**Cookie 被禁用怎么办?**最常用的就是利用 URL 重写把 Session ID 直接附加在 URL 路径的后面。
GET和POST分别是什么?哪个更高效?区别是分别?
GET和POST分别是什么?
GET和POST都是HTTP协议中的两种发送请求的方法,由于HTTP底层是TCP/IP。所以GET和POST的底层也是TCP/IP。最直观的区别就是 GET 把参数包含在 URL 中,POST 通过 request body(消息主体) 传递参数。
GET和POST能做的事情是一样一样的。如果给GET加上request body,或者给POST带上url参数,技术上是完全行的通的。也就是说,GET和POST在本质上没什么区别。 但是如果真的一点区别都没有,那么这个问题也就不存在了,所以,两者之间最重大的区别就是:
GET产生一个TCP数据包;POST产生两个TCP数据包。
哪一个更高效?
GET比POST更高效。具体点说来就是:对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。这样看起来,因为POST需要两步,时间上消耗的要多一点,所以GET比POST更有效。
是否可以用GET替换POST来优化网站性能?
不可以。原因如下:
**原因一:**get与post都有自己的语义,不能随便混用。
**原因二:**如果网络环境好的话,发一次包的时间和发两次包的时间差别基本可以无视。如果网络环境差的话,两次包的TCP在验证数据包完整性上,有非常大的优点。
原因三: 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。
**注意:**存放在请求行和请求体的不是方法, 而是请求/提交的数据, post和get方法都是在请求行中。
GET和POST区别总结
**精简版区别:**Get / post区别:可缓存/不可;保留历史参数/不留;信息可见不安全/较安全;长度限制/不限制
Get方法的含义是请求从服务器获取资源,而POST是向URI指定的资源提交数据
GET数据明文存放在http请求行的url之后,存在暴露敏感信息的问题,而POST则是将提交的数据放在http请求报文的请求体中(即GET参数通过URL传递,POST放在Request body中),所以POST比GET更安全
GET请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。GET请求只能进行URL编码,只接受ASCII字符,而不是unicode,即所有非ASCII字符都要编码之后再传输;而POST支持多种编码方式。
受浏览器对URL长度的限制,GET传送数据量不超过2KB。POST传送数据量则一般无此限制,但实际上post所能传递的数据量大小取决于服务器的设置和内存大小;(总体来说,少量的数据使用GET,大量的数据使用POST。 )
GET产生一个TCP数据包,浏览器会把http header和data一并发送出去,服务器响应200(返回数据); POST产生两个TCP数据包,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
GET用于请求数据,不能改变服务器的数据,一般用于从服务器获取数据,是幂等的;POST用于提交数据,可以改变服务器的数据,不是幂等的;
幂等:多次执行相同的操作,结果是相同的;
GET请求可以被浏览器主动缓存,下一次若传输数据相同,则优先返回缓存中的内存,以加快显示速度。POST请求不会,除非手动设置一下;
GET请求参数会被完整地保存在浏览器历史记录中,POST请求参数则不会保留。
Cookie和Session
Cookie
HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使得它能够处理大量事务,HTTP/1.1 引入 Cookie 来保存状态信息。
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)
Cookie的用途:
- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
Session
利用Session将用户信息存储在服务器端,更具有安全性。
Session可以存储在服务器上的文件、数据库或者内存中。也可以存储在Redis这种内存型数据库中,效率更高。
使用Session维护用户登录状态的过程如下:
- 用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中;
- 服务器验证该用户名和密码,如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID;
- 服务器返回的响应报文的 Set-Cookie 首部字段包含了这个 Session ID,客户端收到响应报文之后将该 Cookie 值存入浏览器中;
- 客户端之后对同一个服务器进行请求时会包含该 Cookie 值,服务器收到之后提取出 Session ID,从 Redis 中取出用户信息,继续之前的业务操作。
注意:Session ID 的安全性问题,不能让它被恶意攻击者轻易获取,那么就不能产生一个容易被猜到的 Session ID 值。此外,还需要经常重新生成 Session ID。在对安全性要求极高的场景下,例如转账等操作,除了使用 Session 管理用户状态之外,还需要对用户进行重新验证,比如重新输入密码,或者使用短信验证码等方式。
cookie和session的区别
1) 了解cookie和session
首先它们都是用于给无状态的http提供身份认证的功能
- cookie是服务器在本机存放的小段文本,并随每一个请求发送至同一服务器。cookie分为会话cookie(不设置过期时间,关闭浏览器窗口cookie即失效,保存在内存中)和持久cookie(存储在客户端磁盘上,其有效时间在服务器响应头中被指定,关闭再打开浏览器cookie仍存在,直至达到过期时间)。类似于检查通行证(即请求报文中附带的cookie)来确定用户身份
- session则一般是利用session id实现的,session id是浏览器第一次发送请求时服务器自动生成的唯一标识,并返回给浏览器,浏览器再次访问服务器时,cookie中携带该session id,服务器根据该session id将session检索出来。类似于在服务器上建立一个客户档案,客户来访时需要查询客户档案
2) Cookie和session区别——速记版本
- 客户端/服务器;
- 有限制/无限制;
- 直接查找篡改/加密存在服务器中;
- 关闭浏览器消失/存在于服务器一段时间,消耗资源;
3) Cookie和session区别——详细概括
- cookie是存放在客户端,用于记录用户信息的,比如自动填充用户名和密码;session是存放在服务器端的,用于记录用户的状态,比如购物车的实现。
- 有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般时效时间较短,客户端关闭或者 Session 超时都会失效。
- **cookie不太安全,**可以分析存放在本地的cookie进行cookie欺骗,(也可以用加密算法加密后进行存放),session存放于服务器的内存中,所以安全性高
- 单个cookie保存数据不能超过4k,session没有对存储数据量的限制,但出于对服务器的性能考虑,Session 内不要存放过多的数据,并且需要设置 Session 删除机制。
Session依赖session_id,而session_id存在cookie中,如果浏览器禁用了cookie,session也会失效,解决办法,将session_id拼接到url中
Session和Cookie应该如何去选择(适用场景)?
- Cookie 只能存储 ASCII 码字符串,而 Session 则可以存储任何类型的数据,因此在考虑数据复杂性时首选 Session;
- Cookie 存储在浏览器中,容易被恶意查看。如果非要将一些隐私数据存在 Cookie 中,可以将 Cookie 值进行加密,然后在服务器进行解密;
- 对于大型网站,如果用户所有的信息都存储在 Session 中,那么开销是非常大的,因此不建议将所有的用户信息都存储到 Session 中。
为什么服务器会缓存这一项功能?如何实现?
原因:
- 缓解服务器压力;
- 降低客户端获取资源的延迟:缓存通常位于内存中,读取缓存的速度更快。并且缓存服务器在地理位置上也有可能比源服务器来得近,例如浏览器缓存。
实现方法
- 让代理服务器进行缓存;
- 让客户端浏览器进行缓存
Web性能优化技术
- DNS查询优化
- 客户端缓存
- 优化TCP连接
- 避免重定向
- 网络边缘的缓存
- 条件缓存
- 压缩和代码极简化
- 图片优化
URL和URI的区别是什么
- URI(Uniform Resource Identifier) 是统一资源标志符,可以唯一标识一个资源。
- URL(Uniform Resource Locator) 是统一资源定位符,可以提供该资源的路径。它是一种具体的 URI,即 URL 可以用来标识一个资源,而且还指明了如何 locate 这个资源。
URI 的作用像身份证号一样,URL 的作用更像家庭住址一样。URL 是一种具体的 URI,它不仅唯一标识资源,而且还提供了定位该资源的信息。
单条记录高并发访问的优化
服务器端:
- 使用缓存,如redis等
- 使用分布式架构进行处理
- 将静态页面和静态资源存储在静态资源服务器,需要处理的数据使用服务器进行计算后返回
- 将静态资源尽可能在客户端进行缓存
- 采用ngnix进行负载均衡 (nginx读作恩静埃克斯 = Engine X)
数据库端:
- 数据库采用主从赋值,读写分离措施
- 建立适当的索引
- 分库分表
服务器高并发的解决方案
- 应用数据与静态资源分离 将静态资源(图片,视频,js,css等)单独保存到专门的静态资源服务器中,在客户端访问的时候从静态资源服务器中返回静态资源,从主服务器中返回应用数据。
- 客户端缓存 因为效率最高,消耗资源最小的就是纯静态的html页面,所以可以把网站上的页面尽可能用静态的来实现,在页面过期或者有数据更新之后再将页面重新缓存。或者先生成静态页面,然后用ajax异步请求获取动态数据。
- 集群和分布式 (集群是所有的服务器都有相同的功能,请求哪台都可以,主要起分流作用) (分布式是将不同的业务放到不同的服务器中,处理一个请求可能需要使用到多台服务器,起到加快请求处理的速度。) 可以使用服务器集群和分布式架构,使得原本属于一个服务器的计算压力分散到多个服务器上。同时加快请求处理的速度。
- 反向代理 在访问服务器的时候,服务器通过别的服务器获取资源或结果返回给客户端。
DHCP配置主机信息
- 假设主机最开始没有 IP 地址以及其它信息,那么就需要先使用 DHCP 来获取。
- 主机生成一个 DHCP 请求报文,并将这个报文放入具有目的端口 67 和源端口 68 的 UDP 报文段中。
- 该报文段则被放入在一个具有广播 IP 目的地址(255.255.255.255) 和源 IP 地址(0.0.0.0)的 IP 数据报中。
- 该数据报则被放置在 MAC 帧中,该帧具有目的地址 FF:FF:FF:FF:FF:FF,将广播到与交换机连接的所有设备。
- 连接在交换机的 DHCP 服务器收到广播帧之后,不断地向上分解得到 IP 数据报、UDP 报文段、DHCP 请求报文,之后生成 DHCP ACK 报文,该报文包含以下信息:IP 地址、DNS 服务器的 IP 地址、默认网关路由器的 IP 地址和子网掩码。该报文被放入 UDP 报文段中,UDP 报文段有被放入 IP 数据报中,最后放入 MAC 帧中。
- 该帧的目的地址是请求主机的 MAC 地址,因为交换机具有自学习能力,之前主机发送了广播帧之后就记录了 MAC 地址到其转发接口的交换表项,因此现在交换机就可以直接知道应该向哪个接口发送该帧。
- 主机收到该帧后,不断分解得到 DHCP 报文。之后就配置它的 IP 地址、子网掩码和 DNS 服务器的 IP 地址,并在其 IP 转发表中安装默认网关。
DNS
DNS是什么
DNS是应用层协议,事实上是为其他应用层协议工作的,包括不限于HTTP、SMTP以及FTP,用于将用户提供的主机名(域名)解析为IP地址。
DNS工作原理
将主机域名转换为ip地址,属于应用层协议,使用UDP传输。
过程:
- 当用户输入域名时,浏览器先检查自己的缓存中(如在chrome浏览器中输入:chrome://dns/)是否包含这个域名映射的ip地址,有解析结束。
- 若没命中,则检查操作系统缓存(如Windows的hosts,linux系统存在/etc/hosts中)中有没有解析过的结果,有解析结束。
- 若无命中,浏览器会发出一个DNS请求到本地域名服务器,本地域名服务器一般是你的网络接入服务商提供,比如中国电信,中国移动等。
- DNS请求到达本地域名服务器后,本地域名服务器会首先查询它的缓存记录,如果存在此条记录,直接返回结果,**此过程是递归查询。**如果没有,本地域名服务器向根域名服务器查询;
- 本地域名服务器继续根域名服务器发出请求,根据跟域名服务器收到请求之后,告诉本地域名服务器,下一次应该查询的顶级域名服务器的IP地址;
- 本地域名服务器向顶级域名服务器发起查询。顶级域名服务器告诉本地域名服务器,下一次应查询的权限域名服务器IP地址
- 本地域名服务器向权限域名服务器发起查询。权限域名服务器告诉本地域名服务器所查询的IP地址。
- 本地域名服务器缓存这个域名和对应的ip, 把解析的结果返回给用户,用户根据TTL值缓存到本地系统缓存中,域名解析过程至此结束
总结: 检查浏览器缓存;检查操作系统内缓存;主机向本地域名服务器查询一般采用递归查询;本地域名服务器向根域名服务器查询采用迭代查询。
**DNS缓存:**浏览器缓存(chrome:😕/dns/)、系统缓存(hosts)、路由器缓存、IPS服务器缓存、根域名服务器缓存、顶级域名服务器缓存、权限域名服务器缓存
DNS的两种解析方式:递归查询和迭代查询
为什么域名解析用UDP
因为UDP快啊!使用UDP的DNS协议只要一个请求、一个应答就好了。而使用基于TCP的DNS协议要三次握手、发送数据以及应答、四次挥手,但是UDP协议传输内容不能超过512字节。
不过客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。
DNS负载均衡是什么策略
当一个网站有足够多的用户的时候,假如每次请求的资源都位于同一台机器上面,那么这台机器随时可能会崩掉。处理办法就是用DNS负载均衡技术,它的原理是在DNS服务器中为同一个主机名配置多个IP地址,在应答DNS查询时,DNS服务器对每个查询将以DNS文件中主机记录的IP地址按顺序返回不同的解析结果,将客户端的访问引导到不同的机器上去,使得不同的客户端访问不同的服务器,从而达到负载均衡的目的。例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等。
一个IP配置多个域名,靠什么识别?
- 靠host主机名区分
- 靠端口号区分
传输层
UDP和TCP首部格式
首部字段只有 8 个字节,包括源端口、目的端口、长度、检验和。12 字节的伪首部是为了计算检验和临时添加的。
序号(32bit) :用于对字节流进行编号,例如序号为 301,表示第一个字节的编号为 301,如果携带的数据长度为 100 字节,那么下一个报文段的序号应为 401。用来解决网络包乱序问题。
确认号(32bit) :期望收到的下一个报文段的序号。例如 B 正确收到 A 发送来的一个报文段,序号为 501,携带的数据长度为 200 字节,因此 B 期望下一个报文段的序号为 701,B 发送给 A 的确认报文段中确认号就为 701。用来解决不丢包问题。
数据偏移(4bit) :指的是数据部分距离报文段起始处的偏移量,实际上指的是首部的长度。最大为15,即60字节
标志位:
- 确认 ACK :当 ACK=1 时确认号字段有效,否则无效。TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 置 1。
- 同步 SYN :在连接建立时用来同步序号。当 SYN=1,ACK=0 时表示这是一个连接请求报文段。若对方同意建立连接,则响应报文中 SYN=1,ACK=1。
- 终止 FIN :用来释放一个连接,当 FIN=1 时,表示此报文段的发送方的数据已发送完毕,并要求释放连接。
- **RST:**该位为1 时,表示 TCP连接中出现异常必须强制断开连接。
窗口 :窗口值作为接收方让发送方设置其发送窗口的依据。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。
TCP与UDP的区别
1)TCP是面向连接的传输层协议,传输数据前先要建立连接,数据传输结束后要释放连接。UDP是不需要连接,即刻传输数据。
2)TCP是一对一的两点服务,即一条连接只有两个端点。UDP支持一对一、一对多、多对多的交互通信。即:TCP只适用于一对一单播,UDP可用于广播通信
3)可靠性:TCP 提供可靠的传输服务,TCP 在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制。通过 TCP 连接传输的数据,无差错、不丢失、不重复、并且按序到达。UDP是尽最大努力交付,不保证可靠交付数据。
4)TCP有拥塞控制和流量控制机制,保证数据传输的安全性。UDP则没有,即使网络非常拥堵了,也不会影响UDP的发送速率。
5)首部开销:TCP首部长度较长,会有一定的开销,首部在没有使用「选项」字段时是20个字节,如果使用了「选项」则会变长的。UDP首部只有8个字节,并且是固定不变的,开销较小。
6)TCP是面向字节流的,没有边界,会出现粘包问题,但保证顺序和可靠。UDP是面向报文的,一个包一个包的发送,是有边界的,不会出现粘包问题,但可能会丢包和乱序。
7)分片不同:
- TCP的数据大小如果大于MSS大小,则会在传输层进行分片,目标主机收到后,也同样在传输层组装TCP数据包,如果中途丢失了一个分片,只需要传输丢失的这个分片。
- UDP的数据大小如果大于MTU大小,则会在IP层进行分片,目标主机收到后,在P层组装完数据,接着再传给传输层,但是如果中途丢了一个分片,在实现可靠传输的UDP时则就需要重传所有的数据包,这样传输效率非常差,所以通常UDP的报文应该小于MTU。
8)是否有状态:
TCP传输是有状态的,这个有状态说的是 TCP 会去记录自己发送消息的状态比如消息是否发送了、是否被接收了等等。为此 ,TCP 需要维持复杂的连接状态表。
UDP是无状态服务,不管发出去之后的事情了。
选择TCP还是UDP?
- UDP 一般用于即时通信,比如: 语音、 视频 、直播等等。这些场景对传输数据的准确性要求不是特别高。要求性能和速度的时候,使用UDP更加合适。
- TCP 用于对传输准确性要求特别高的场景,比如文件传输、发送和接收邮件、远程登录等等。如果强调数据的完整性和正确性用TCP
端口有效范围
0-1023为知名端口号,比如其中HTTP是80,FTP是20(数据端口)、21(控制端口)
UDP和TCP报头使用两个字节存放端口号,所以端口号的有效范围是从0到65535。动态端口的范围是从1024到65535
什么是TCP粘包/拆包?发生的原因?如何解决?
TCP 发送数据时会根据 TCP 缓冲区的实际情况进行包的划分,一个完整的包可能会被 TCP 拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是 TCP 粘包和拆包问题。
发生TCP粘包的原因:
- 发送的数据小于TCP缓冲区的大小,TCP将缓冲区的数据(数据属于多条业务内容)一次发送出去可能就发生粘包;
- 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包;
发生TCP拆包的原因:
- 待发送数据大于最大报文段,TCP在传输前将进行拆包;
- 发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包;
解决方法:
消息定长。发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
发送端给每个数据包添加包首部,首部中包含数据包的长度,这样接收端收到数据后,通过该字段就可以知道每个数据包的实际长度;
在数据包之间设置边界,比如增加回车或者空格符等特殊字符进行分割
更复杂的应用层协议。
TCP粘包问题是什么?会如何解决
TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
- 由TCP连接复用造成的粘包问题。
- 因为TCP默认会使用Nagle算法,此算法会导致粘包问题。
- 只有上一个分组得到确认,才会发送下一个分组;
- 收集多个小分组,在一个确认到来时一起发送。
- 数据包过大造成的粘包问题。
- 流量控制,拥塞控制也可能导致粘包。
- 接收方不及时接收缓冲区的包,造成多个包接收
解决:
- Nagle算法问题导致的,需要结合应用场景适当关闭该算法
- 尾部标记序列。通过特殊标识符表示数据包的边界,例如\n\r,\t,或者一些隐藏字符。
- 头部标记分步接收。在TCP报文的头部加上表示数据长度。
- 应用层发送数据时定长发送。
封包和拆包是什么,它是基于TCP还是UDP?
封包和拆包都是基于TCP的概念。因为TCP是无边界的流传输,所以需要对TCP进行封包和拆包,确保发送和接收的数据不粘连。
- 封包:封包就是在发送数据报的时候为每个TCP数据包加上一个包头,将数据报分为包头和包体两个部分。包头是一个固定长度的结构体,里面包含该数据包的总长度。
- 拆包:接收方在接收到报文后提取包头中的长度信息进行截取。
使用TCP和UDP的协议
运行于TCP协议之上的协议:
- HTTP协议(端口号:80):超文本传输协议(HTTP,HyperText Transfer Protocol)主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的。
- HTTPS协议(端口号:443):更安全的超文本传输协议(HTTPS,Hypertext Transfer Protocol Secure),身披 SSL 外衣的 HTTP 协议
- FTP协议(使用TCP端口中的20和21这两个端口,其中20用于传输数据,21用于传输控制信息):文件传输协议,提供文件传输服务。使用 FTP 传输文件的好处是可以屏蔽操作系统和文件存储方式。
- SMTP协议(端口号25):简单邮件传输协议,基于TCP协议,用来发送电子邮件。
- POP3(端口号110)/IMAP协议(端口号143):负责邮件接收的协议。
- Telnet协议(端口号23):远程登录协议。通过一个终端登陆到其他服务器。被一种称为 SSH 的非常安全的协议所取代。
- SSH协议(端口号22):SSH(Secure Shell)是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。SSH 建立在可靠的传输协议 TCP 之上。
- ...
运行于UDP协议之上的协议:
- DHCP协议:动态主机配置协议,动态配置IP地址;DHCP客户端发送请求消息到DHCP服务器的68号端口,DHCP服务器回应应答消息给DHCP客户端的67号端口
- DNS协议(端口号53):域名解析协议,将域名转换为IP地址。
- SNMP:简单网络管理协议,端口号161;
- TFTP:简单文件传输协议:端口号69
TCP三次握手
建立一个TCP链接需要三次握手:
- 一开始,客户端和服务端都处于CLOSED 状态。先是服务端主动监听某个端口,处于LISTEN 状态
- 一次握手:客户端随机初始化序列号x,将此置于TCP首部的序号SEQ字段中,同时把SYN标志位置为1,表示SYN报文。接着发送SYN报文给服务端,表示向服务端发起连接,该报文不包含应用层数据,然后客户端进入 SYN_SEND 状态,等待服务器的确认;
- 二次握手:服务端受到客户端的SYN报文后,首先服务端也随机初始化自己的序列号y,将此序号填入TCP首部的序号SEQ字段中,其次把ACK确认号字段填入x + 1,接着把SYN和ACK标志位置为1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于SYN-RECV状态。
- 三次握手:客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文TCP首部 ACK标志位置为1,其次ACK确认号字段填入y + 1,序列号为x + 1, 最后把报文发送给服务端,这次报文可以携带客户到服务器的数据,之后客户端处于ESTABLISHED状态。服务器收到客户端的应答报文后,也进入ESTABLISHED状态。
在socket编程中,客户端执行connect()时,将触发三次握手。可以发现第三次握手是可以携带数据的,前两次握手不可以携带数据。一旦完成三次握手,双方都处于ESTABLISHED 状态,此时连接就已建立完成,客户端和服务端就可以相互发送数据了。
三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。
为什么要三次握手?
三次握手可以初始化socket、序列号和窗口大小并建立TCP连接。三次握手的原因:
- 三次握手才可以阻止重复历史连接的初始化(主要原因):如果旧的SYN报文比新的SYN报文先到达服务端,服务端回应SYN+ACK报文,客户端收到后可以根据自身上下文,判断这是一个历史连接(序列号过期或超时),那么客户端就会发送RST报文给服务端,表示中止这一次连接。如果是两次握手连接,就不能判断当前连接是否是历史连接,所以三次握手可以防止历史连接的初始化。
- 三次握手才可以同步双方的初始序列号:序列号保证接收方去除重复的数据,可以根据数据包的序列号按序接受,可以标识对方收到哪些已经发送的数据包。两次握手只保证了一方的初始序列号能被对方成功接收,没办法保证双方的初始序列号都能被确认接收。
- 三次握手才可以避免资源浪费: 如果只有两次握手,在消息滞留情况下,客户端重复发送多次SYN 报文,那么服务器在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费。
所以,TCP建立连接时,通过三次握手能防止历史连接的建立,能减少双方不必要的资源开销,能帮助双方同步初始化序列号。序列号能够保证数据包不重复、不丢弃和按序传输。
不使用三次握手和四次握手的原因:
- 两次握手︰无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
- 四次握手︰三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。
ISN初始序列号是固定的吗?
三次握手的一个重要功能是客户端和服务端交换ISN,以便让对方知道接下来接收数据的时候如何按序列号组装数据;
如果ISN是固定的,攻击者很容易猜出后续的确认号,因此ISN是动态生成的。
什么是半连接队列
服务器第一次收到客户端的SYN之后,就会处于SYN_RCVD状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。
关于SYN-ACK重传次数:服务器发送完SYN一ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。
三次握手过程中可以携带数据吗?
第一二次不可以,因为如果攻击者在第一次握手时往SYN报文放入大量数据,会让服务器容易受到攻击。而第三次握手可以携带数据,因为客户端已经是established状态,即对于客户端来说连接已经建立,它知道服务器收发能力正常,所以可以携带数据。
TCP四次握手
建立一个连接需要三次握手,而终止一个连接要经过四次挥手(也有将四次挥手叫做四次握手的)。这由TCP的半关闭(half-close)造成的。所谓的半关闭,其实就是TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。
- 第一次握手:客户端打算关闭连接,此时会发送一个TCP首部
FIN
标志位被置为1的FIN报文,即发出连接释放报文段,报文中会指定一个序列号seq = u。之后客户端停止再发送数据,主动关闭TCP连接,进入FIN_WAIT_1(终止等待1)状态,等待服务端的确认。 - 第二次握手:服务端收到FIN报文后,向客户端发送ACK报文(ACK=1,确认号ack=u+1,序号seq=v),且把客户端的序列号 + 1作为ACK报文的序列号,表明已经收到客户端的报文了,此时服务端处于CLOSE_WAIT状态。 此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT_2(终止等待2)状态,等待服务端发出的连接释放报文段。
- 第三次握手:等待服务端处理完数据后,也向客户端发送FIN报文(连接释放报文段,FIN=1,ACK=1,序号seq=w,确认号ack=u+1),且指定一个序列号,此时服务器处于LAST_ACK状态,等待客户端的确认。
- 第四次握手:客户端收到服务端的FIN报文后,回一个ACK应答报文(ACK=1,seq=u+1,ack=w+1),且把服务端的序列号值 +1 作为自己 ACK 报文的确认号值,此时客户端处于 TIME_WAIT状态。服务器收到ACK应答报文后,进入CLOSED状态,至此服务端已经完成连接的关闭。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态,至此客户端也完成连接的关闭。
为什么要四次握手?
TCP是全双工通信,可以双向传输数据。关闭连接时,客户端向服务端发送FIN时,仅仅表示客户端不再发送数据了带还是可以接收数据。服务器收到客户端的FIN报文时,先回一个ACK应答报文表示接收到了断开连接的请求,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送FIN报文给客户端表示完全关闭TCP连接。
为什么TIME_WAIT等待的时间是2MSL
MSL是报文最大生存时间(报文段最长寿命),它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
第四次握手时,客户端发送给服务器的 ACK 有可能丢失,如果服务端没有因为某些原因而没有收到 ACK 的话,服务端就会重发 FIN,如果客户端在 2*MSL 的时间内收到了 FIN,就会重新发送 ACK 并再次等待 2MSL,防止 Server 没有收到 ACK 而不断重发 FIN,保证连接正常关闭。如果客户端不等待,而是发送完ACK报文段后立即释放连接,则无法收到服务端重传的连接释放报文段,所以不会再发送依次确认报文段,服务端就无法正常进入到CLOSED状态。
2MSL就是一个发送和回复所需的最大时间,如果直到 2MSL,Client 都没有再次收到 FIN,那么 Client 推断 ACK 已经被成功接收,则结束 TCP 连接。
所以,原因:
- 保证客户端发送的最后一个ACK报文段能够到达服务端。TIME_WAIT状态就是用来重发可能丢失的ACK报文。
- 防止已失效的连接请求报文段出现在本连接中。A在发送完最后一个ACK报文段后,再经过2MSL,就可以使这个连接所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现旧的连接请求报文段。
服务器出现大量close_wait的连接的原因是什么?有什么解决方法?
close_wait状态是在TCP四次挥手的时候收到FIN但是没有发送自己的FIN时出现的,服务器出现大量close_wait状态的原因有两种:
- 服务器内部业务处理占用了过多时间,都没能处理完业务;或者还有数据需要发送;或者服务器的业务逻辑有问题,没有执行close()方法
- 服务器的父进程派生出子进程,子进程继承了socket,收到FIN的时候子进程处理但父进程没有处理该信号,导致socket的引用不为0无法回收
处理方法:
- 停止应用程序
- 修改程序里的bug
建立连接时,服务器应用被阻塞(或者僵死)
在客户端建立连接的过程中服务端应用处于僵死状态,这种情况在实际中也会经常出现(我们假设仅仅应用程序僵死,而内核没有僵死)。此时会出现什么状态?TCP的三次是否可以完成?客户端是否可以收发数据?
在用户层面我们知道,服务端通过accept接口返回一个新的套接字,这时就可以和客户端进行数据往来了。也就是在用户层面来说,accept返回结果说明3次握手完成了,否则accept会被阻塞。在我们假设的情况下,其实就相当于应用程序无法进行accept操作了。
如果想彻底理解上面我们假设的问题,需要理解两点,一点是accept函数具体做了什么,另外一点是TCP三次握手的本质。
我们先试着理解第一点,accept会通过软中断陷入内核中,最终会调用tcp协议的inet_csk_accept函数,该函数会从队列中查找是否有处于ESTABLISHED状态的套接字。如果有则返回该套接字,否则阻塞当前进程。也就是说这里只是一个查询的过程,并不参与三次握手的任何逻辑。
三次握手的本质是什么呢?实际上就是客户端与服务端一个不断交流的过程,而这个交流过程就是通过3个数据包完成的。而这个数据包的发送和处理实际上都是在内核中完成的。对于TCP的服务端来说,当它收到SYN数据包时,就会创建一个套接字的数据结构并给客户端回复ACK,再次收到客户端的ACK时会将套接字数据结构的状态转换为ESTABLISHED,并将其发送就绪队列中。而这整个过程跟应用程序没有半毛钱的关系。
当上面套接字加入就绪队列时,accept函数就被唤醒了,然后就可以获得新的套接字并返回。但我们回过头来看一下,在accept返回之前,其实三次握手已经完成,也就是连接已经建立了。
另外一个是如果accept没有返回,客户端是否可以发送数据?答案是可以的。因为数据的发送和接受都是在内核态进行的。客户端发送数据后,服务端的网卡会先接收,然后通过中断通知IP层,再上传到TCP层。TCP层根据目的端口和地址将数据存入关联的缓冲区。如果此时应用程序有读操作(例如read或recv),那么数据会从内核态的缓冲区拷贝到用户态的缓存。否则,数据会一直在内核态的缓冲区中。总的来说,TCP的客户端是否可以发送数据与服务端程序是否工作没有任何关系。
当然,如果是整个机器都卡死了,那就是另外一种情况了。这种情况就我们之前分析的第2种情况一直了。因为,由于机器完全卡死,TCP服务端无法接受任何消息,自然也无法给客户端发送任何应答报文。
一个机器能够使用的端口号上限是多少,为什么?可以改变吗?那如果想要用的端口超过这个限制怎么办?
65536.因为TCP的报文头部中源端口号和目的端口号的长度是16位,也就是可以表示2^16=65536个不同端口号,因此TCP可供识别的端口号最多只有65536个。但是由于0到1023是知名服务端口,所以实际上还要少1024个端口号。
而对于服务器来说,可以开的端口号与65536无关,其实是受限于Linux可以打开的文件数量,并且可以通过MaxUserPort来进行配置。
如何确定一个TCP连接
TCP四元组可以唯一确定一个连接,四元组包括:源地址、源端口、目的地址、目的端口。
源地址和目的地址字段(32位)是在IP头部中,作用是通过IP协议发送报文给对方主机。
源端口和目的端口的字段(16位)是在TCP头部中,作用是告诉TCP协议应该把报文发送给哪个进程。
有一个IP的服务器监听了一个端口,他的TCP的最大连接数是多少?
服务器通常固定在某个本地端口上监听,等待客户端的连接请求。
客户端IP和端口是可变的,理论值计算公式:最大TCP连接数 = 客户端的 IP数 X 客户端的端口数。
对IPv4,客户端的IP数最多为2^32, 客户端的端口数最多为216,那服务端单机最大TCP连接数约为248。
当然,服务端最大并发TCP连接数远不能达到理论上限。
- 首先主要是文件描述符限制,Socket都是文件,所以首先要通过ulimit 配置文件描述符的数目;
- 另一个是内存限制,每个TCP连接都要占用一定内存,操作系统的内存是有限的。
拔掉网线后,原来的TCP连接还存在吗?
拔掉网线后, 原本的 TCP 连接还存在吗? - 小林coding - 博客园
拔掉网线这个动作并不会影响传输层。实际上,TCP 连接在 Linux 内核中是一个名为 struct socket
的结构体,该结构体的内容包含 TCP 连接的状态等信息。当拔掉网线的时候,操作系统并不会变更该结构体的任何内容,所以 TCP 连接的状态也不会发生改变。
所以, 针对这个问题,要分场景来讨论:
拔掉网线后,有数据传输
- 在客户端拔掉网线后,如果服务端发送了数据报文,那么在服务端重传次数没有达到最大值之前,客户端就插回了网线,那么双方原本的 TCP 连接还是能正常存在,就好像什么事情都没有发生。
- 在客户端拔掉网线后,如果服务端发送了数据报文,在客户端插回网线之前,服务端重传次数达到了最大值时,服务端就会断开 TCP 连接。等到客户端插回网线后,向服务端发送了数据,因为服务端已经断开了与客户端相同四元组的 TCP 连接,所以就会回 RST 报文,客户端收到后就会断开 TCP 连接。至此, 双方的 TCP 连接都断开了。
拔掉网线后,没有数据传输:
如果双方都没有开启 TCP keepalive 机制,那么在客户端拔掉网线后,如果客户端一直不插回网线,那么客户端和服务端的 TCP 连接状态将会一直保持存在。
如果双方都开启了 TCP keepalive 机制,那么在客户端拔掉网线后,如果客户端一直不插回网线,TCP keepalive 机制会探测到对方的 TCP 连接没有存活,于是就会断开 TCP 连接。而如果在 TCP 探测期间,客户端插回了网线,那么双方原本的 TCP 连接还是能正常存在。
TCP keepalive 机制具体是怎么样的?定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。
除了客户端拔掉网线的场景,还有客户端「宕机和杀死进程」的两种场景。
第一个场景,客户端宕机这件事跟拔掉网线是一样无法被服务端的感知的,所以如果在没有数据传输,并且没有开启 TCP keepalive 机制时,服务端的 TCP 连接将会一直处于 ESTABLISHED 连接状态,直到服务端重启进程。
所以,我们可以得知一个点。在没有使用 TCP 保活机制,且双方不传输数据的情况下,一方的 TCP 连接处在 ESTABLISHED 状态时,并不代表另一方的 TCP 连接还一定是正常的。
第二个场景,杀死客户端的进程后,客户端的内核就会向服务端发送 FIN 报文,与客户端进行四次挥手。
所以,即使没有开启 TCP keepalive,且双方也没有数据交互的情况下,如果其中一方的进程发生了崩溃,这个过程操作系统是可以感知的到的,于是就会发送 FIN 报文给对方,然后与对方进行 TCP 四次挥手。
既然IP层会分片,为什么TCP层还需要MSS呢?
如果一个IP分片丢失,整个IP报文的所有分片就要重传。因为IP层本身没有超时重传机制,它由传输层的TCP来负责超时和重传。
所以,由IP层进行分片传输,是没有效率的。为了达到最佳的传输效能,TCP协议在建立连接的时候通常要协商双方的MSS值,当TCP层发现数据超时MSS时,就会先分片,当然有它形成的IP包长度不会大于MTU,自然不用IP分片了。
经过TCP层分片后,如果一个TCP分片丢失后,进行重发时也是以MSS为单位,而不用重传所有的分片,增加了重传的效率。
TCP如何保证传输的可靠性?
确认应答+序列号:TCP给发送的每一个包一个序列号,接收方收到报文就会确认并对数据包进行排序,把有序数据传送给应用层。利用序列号可以去重、确认应答、排序。
**超时重传:**当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
数据校验:TCP报文头有校验和,用于校验报文(首部加数据)在传输过程中是否损坏。如果收到段的检验和有差错,TCP 将丢弃这个报文段。
校验和求法:发送的数据包的二进制相加然后取反。
这种方法并不能保证数据传输出错。因为这种校验方法是累积和,如果过程中前后的比特位颠倒了,则校验和的计算结果一样,那么接收端无法检查出这是错误的数据。
**解决方法:**传输前使用MD5加密数据获得摘要,跟数据一起发送到服务器。
对失序数据包重新排序以及去重:TCP 为了保证不发生丢包,就给每个包一个序列号,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据就可以实现数据包去重。
流量控制:当接收方来不及处理发送方的数据,能通过滑动窗口,提示发送方降低发送的速率,防止包丢失。
拥塞控制:当网络拥塞时,通过拥塞窗口,减少数据的发送,防止包丢失。
UDP如何实现可靠传输
因为UDP是无连接的协议,所以在传输层上无法保证可靠传输,要想实现可靠传输,只能从应用层实现。需要实现seq/ack机制,重传机制和窗口确认机制。
就要接收方收到UDP之后回复个确认包,发送方有个机制,收不到确认包就要重新发送,每个包有递增的序号,接收方发现中间丢了包就要发重传请求,当网络太差时候频繁丢包,防止越丢包越重传的恶性循环,要有个发送窗口的限制,发送窗口的大小根据网络传输情况调整,调整算法要有一定自适应性。
滑动窗口机制(流量控制)
流量控制介绍
TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。
为什么需要流量控制? 这是因为双方在通信的时候,发送方的速率与接收方的速率是不一定相等,如果发送方的发送速率太快,会导致接收方处理不过来。如果接收方处理不过来的话,就只能把处理不过来的数据存在 接收缓冲区(Receiving Buffers) 里(失序的数据包也会被存放在缓存区里)。如果缓存区满了发送方还在狂发数据的话,接收方只能把收到的数据包丢掉。出现丢包问题的同时又疯狂浪费着珍贵的网络资源。因此,我们需要控制发送方的发送速率,让接收方与发送方处于一种动态平衡。
需要注意的是:发送端不等同于客户端,接收端不等同于服务端。
TCP会话的两端各有一个发送缓冲区与接收缓冲区,两端都各自维护一个发送窗口和一个接收窗口。
- 发送窗口:限制发送方可以发送的数据大小,其大小由接收端返回的TCP报文段中窗口字段来控制。
- 接收窗口:用来标记可以接受的数据大小;大小取 决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。
TCP发送窗口可以划分为四个部分:
- 已经发送并且确认的TCP段(已经发送并确认);
- 已经发送但是没有确认的TCP段(已经发送未确认);
- 未发送但是接收方准备接收的TCP段(可以发送);
- 未发送并且接收方也并未准备接受的TCP段(不可发送)。
TCP发送窗口结构图:
- SND.WND :发送窗口。
- SND.UNA:Send Unacknowledged 指针,指向发送窗口的第一个字节。
- SND.NXT:Send Next 指针,指向可用窗口的第一个字节。
可用窗口大小 = SND.UNA + SND.WND - SND.NXT
。
TCP接收窗口可以划分为三个部分:
- 已经接收并且已经确认的 TCP 段(已经接收并确认);
- 等待接收且允许发送方发送 TCP 段(可以接收未确认);
- 不可接收且不允许发送方发送TCP段(不可接收)。
如果接收端读取数据快,接收窗口可能会扩大。 否则,它可能会缩小。TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最大为65535。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。接收窗口的大小是根据接收端处理数据的速度动态调整的。 于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。接收窗口的大小是约等于发送窗口的大小。
当滑动窗口为 0 时,发送方一般不能再发送数据报,但有两种情况除外,一种情况是可以发送紧急数据。例如,允许用户终止在远端机上的运行进程。另一种情况是发送方可以发送一个 1 字节的数据报来通知接收方重新声明它希望接收的下一字节及发送方的滑动窗口大小。
采用滑动窗口会有什么问题(死锁可能,糊涂窗口综合征)?
考虑一种特殊的情况,就是接收方若没有缓存足够使用,就会发送零窗口大小的报文,此时发送放将发送窗口设置为0,停止发送数据。之后接收方有足够的缓存,发送了非零窗口大小的报文,但是这个报文在中途丢失的,那么发送方的发送窗口就一直为零导致死锁。
解决这个问题,TCP为每一个连接设置一个持续计时器(persistence timer)。只要TCP的一方收到对方的零窗口通知,就启动该计时器,周期性的发送一个零窗口探测报文段。对方就在确认这个报文的时候给出现在的窗口大小(注意:TCP规定,即使设置为零窗口,也必须接收以下几种报文段:零窗口探测报文段、确认报文段和携带紧急数据的报文段)。
TCP 的拥塞控制是怎么实现的?
在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。而流量控制是个端到端的问题,所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。
为了进行拥塞控制,TCP 发送方要维持一个 拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。
TCP的拥塞控制采用了四种算法: 慢开始 、 拥塞避免 、快重传 和 快恢复。
- 慢开始: 慢开始算法的思路是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么可能会引起网络阻塞。所以由小到大逐渐增大拥塞窗口数值(即发送窗口)。cwnd 初始值为 一个最大报文段MSS的数值,每经过一个传播轮次,cwnd 加倍。为了防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限ssthresh状态变量。当cwnd<ssthresh,使用慢开始算法,当大于时,停止使用慢开始算法而改用拥塞避免算法;如果等于,既可以使用慢开始算法,也可以使用拥塞避免算法。
- 拥塞避免: 拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢增大,即每经过一个往返时间 RTT 就把发送方的 拥塞窗口cwnd 加 1,而不是加倍(加法增大)。无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据是没有收到确认),就把慢开始门限ssthresh设置为出现拥塞时发送方窗口值的一半,然后把拥塞窗口重新设置为1,执行慢开始算法,这样迅速减少主机发送到网络中的分组数。
- 快重传:有时个别报文段在网络中丢失但实际上网络没有拥塞,如果发送方迟迟没有收到确认,就误以为发生了拥塞,导致启动慢开始算法,把拥塞窗口设置为1,降低了传输速率。**快重传可以避免这个问题。**快重传算法要求接收方每收到一个失序的报文段后就立即发出重复确认,使发送方及早知道有报文段没有到达对方。发送方只要一连收到三个重复确认就立即重传对方尚未收到的报文段,而不必继续等待重传计时器到期。
- 快恢复: 当发送方连续收到三个重复确认,就把慢开始门限ssthresh减半,接着把cwnd值设置为慢开始门限ssthresh减半后的数值(乘法减少),然后执行拥塞避免算法,使拥塞窗口缓慢线性增加。
为啥快速重传是选择3次ACK
主要的考虑还是要区分包的丢失是由于链路故障还是乱序等其他因素引发。
两次duplicated ACK时很可能是乱序造成的!三次duplicated ACK时很可能是丢包造成的!四次duplicated ACK更更更可能是丢包造成的,但是这样的响应策略太慢。丢包肯定会造成三次duplicated ACK!综上是选择收到三个重复确认时窗口减半效果最好,这是实践经验。
因为网络传输是不可靠的,丢包、乱序和复制等情况,如果出现三次以上DupAck的就认为丢包的可能性很高,可以进入快速重传机制。
SYN攻击
如果攻击者短时间伪造不同IP地址的SYN报文,服务端每收到一个SYN报文,就进入SYN_RCVD状态,但服务端发送的ACK + SYN报文,无法得到未知IP主机的ACK应答,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞,大量消耗服务器内存,甚至系统瘫痪。SYN 攻击是一种典型的 DoS/DDoS 攻击。
检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。在 Linux/Unix 上可以使用系统自带的 netstats 命令来检测 SYN 攻击。
netstat -n -p TCP | grep SYN_RECV
常见解决方法
- 降低SYN timeout时间: 使得服务器在没收到确认报文后尽快释放半连接的占用
- 采用SYN cookie设置: 给每一个请求连接的ip地址分配一个cookie,短时间内如果连续收到某个IP的重复的SYN报文,就认定收到了攻击,以后会自动丢弃该ip地址传送过来的包
- 增加最大半连接数
- 过滤网关防护
网络层
网络层常见协议
协议 | 名称 | 作用 |
---|---|---|
IP | 网际协议 | IP协议不但定义了数据传输时的基本单元和格式,还定义了数据报的递交方法和路由选择 |
ICMP | Internet控制报文协议 | ICMP就是一个“错误侦测与回报机制”,其目的就是让我们能够检测网路的连线状况﹐也能确保连线的准确性,是ping和traceroute的工作协议 |
RIP | 路由信息协议 | 使用“跳数”(即metric)来衡量到达目标地址的路由距离 |
IGMP | Internet组管理协议 | 用于实现组播、广播等通信 |
**Note:**在OSI模型中ARP协议属于链路层; 而在TCP/IP模型中,ARP协议属于网络层。
IP数据报格式
- 版本 : 有 4(IPv4)和 6(IPv6)两个值;
- 首部长度 : 占 4 位,因此最大值为 15。值为 1 表示的是 1 个 32 位字的长度,也就是 4 字节。因为固定部分长度为 20 字节,因此该值最小为 5。如果可选字段的长度不是 4 字节的整数倍,就用尾部的填充部分来填充。
- 区分服务 : 用来获得更好的服务,一般情况下不使用。
- 总长度 : 包括首部长度和数据部分长度。
- 生存时间 :TTL,它的存在是为了防止无法交付的数据报在互联网中不断兜圈子。以路由器跳数为单位,当 TTL 为 0 时就丢弃数据报。
- 协议 :指出携带的数据应该上交给哪个协议进行处理,例如 ICMP、TCP、UDP 等。
- 首部检验和 :因为数据报每经过一个路由器,都要重新计算检验和,因此检验和不包含数据部分可以减少计算的工作量。
- 标识 : 在数据报长度过长从而发生分片的情况下,相同数据报的不同分片具有相同的标识符。
- 片偏移 : 和标识符一起,用于发生分片的情况。片偏移的单位为 8 字节。
IP地址分类
一般可以这么认为,IP地址=网络号+主机号。
- 网络号:它标志主机所连接的网络地址表示属于互联网的哪一个网络。
- 主机号:它标志主机地址表示其属于该网络中的哪一台主机。
IP地址分为A,B,C,D,E五大类:
- A类地址(1~126):以0开头,网络号占前8位,主机号占后面24位。
- B类地址(128~191):以10开头,网络号占前16位,主机号占后面16位。
- C类地址(192~223):以110开头,网络号占前24位,主机号占后面8位。
- D类地址(224~239):以1110开头,保留位多播地址。
- E类地址(240~255):以1111开头,保留位为将来使用
**子网划分:**通过在主机号字段中拿一部分作为子网号,把两级 IP 地址划分为三级 IP 地址。
IP 地址 ::=
要使用子网,必须配置子网掩码。外部网络看不到子网的存在。
无分类编制CIDR: 消除了传统 A 类、B 类和 C 类地址以及划分子网的概念,使用网络前缀和主机号来对 IP 地址进行编码,网络前缀的长度可以根据需要变化。
IP 地址 ::=
CIDR 的记法上采用在 IP 地址后面加上网络前缀长度的方法,例如 128.14.35.7/20 表示前 20 位为网络前缀。
ARP
什么是MAC地址
MAC 地址的全称是 媒体访问控制地址(Media Access Control Address)。如果说,互联网中每一个资源都由 IP 地址唯一标识(IP 协议内容),那么一切网络设备都由 MAC 地址唯一标识。
MAC地址长度为6字节(48比特),MAC 地址有一个特殊地址:FF-FF-FF-FF-FF-FF(全 1 地址),该地址表示广播地址。
ARP协议解决了什么问题?
ARP 协议,全称 地址解析协议(Address Resolution Protocol),它解决的是网络层地址和链路层地址之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题
ARP协议工作原理
ARP协议完成了IP地址与物理地址的映射。每一个主机都设有一个 ARP 高速缓存,里面有所在的局域网上的各主机和路由器的 IP 地址到硬件地址的映射表。
如果主机 A 知道主机 B 的 IP 地址,但是 ARP 高速缓存中没有该 IP 地址到 MAC 地址的映射,此时主机 A 通过广播的方式发送 ARP 请求分组(在发送自己的 ARP 请求时,同时会带上自己的 IP 地址到硬件地址的映射),主机 B 收到该请求后会发送 ARP 响应分组给主机 A 告知其 MAC 地址,并在自己的高速缓存中保存主机A的IP到MAC的映射,随后主机 A 向其高速缓存中写入主机 B 的 IP 地址到 MAC 地址的映射。
在一个局域网内,每个网络设备都自己维护了一个 ARP 表,ARP 表记录了某些其他网络设备的 IP 地址-MAC 地址映射关系,该映射关系以 <IP, MAC, TTL>
三元组的形式存储。其中,TTL 为该映射关系的生存周期,典型值为 20 分钟,超过该时间,该条目将被丢弃。
ARP 的工作原理将分两种场景讨论:
- 同一局域网内的 MAC 寻址;
- 从一个局域网到另一个局域网中的网络设备的寻址
同一局域网内的MAC寻址:
为了达成这一目标,主机 A 将不得不通过 ARP 协议来获取主机 B 的 MAC 地址,并将 IP 报文封装成链路层帧,发送到下一跳上。在该局域网内,关于此将按照时间顺序,依次发生如下事件:
主机 A 检索自己的 ARP 表,发现 ARP 表中并无主机 B 的 IP 地址对应的映射条目,也就无从知道主机 B 的 MAC 地址。
主机 A 将构造一个 ARP 查询分组,并将其广播到所在的局域网中。
ARP 分组是一种特殊报文,ARP 分组有两类,一种是查询分组,另一种是响应分组,它们具有相同的格式,均包含了发送和接收的 IP 地址、发送和接收的 MAC 地址。当然了,查询分组中,发送的 IP 地址,即为主机 A 的 IP 地址,接收的 IP 地址即为主机 B 的 IP 地址,发送的 MAC 地址也是主机 A 的 MAC 地址,但接收的 MAC 地址绝不会是主机 B 的 MAC 地址,而是一个特殊值——
FF-FF-FF-FF-FF-FF
,之前说过,该 MAC 地址是广播地址,也就是说,查询分组将广播给该局域网内的所有设备。主机 A 构造的查询分组将在该局域网内广播,理论上,每一个设备都会收到该分组,并检查查询分组的接收 IP 地址是否为自己的 IP 地址,如果是,说明查询分组已经到达了主机 B,否则,该查询分组对当前设备无效,丢弃之。
主机 B 收到了查询分组之后,验证是对自己的问询,接着构造一个 ARP 响应分组,该分组的目的地只有一个——主机 A,发送给主机 A。同时,主机 B 提取查询分组中的 IP 地址和 MAC 地址信息,在自己的 ARP 表中构造一条主机 A 的 IP-MAC 映射记录。
ARP 响应分组具有和 ARP 查询分组相同的构造,不同的是,发送和接受的 IP 地址恰恰相反,发送的 MAC 地址为发送者本身,目标 MAC 地址为查询分组的发送者,也就是说,ARP 响应分组只有一个目的地,而非广播。
主机 A 终将收到主机 B 的响应分组,提取出该分组中的 IP 地址和 MAC 地址后,构造映射信息,加入到自己的 ARP 表中。
总结来说,ARP 协议是一个广播问询,单播响应协议。
不同局域网内的MAC寻址:
更复杂的情况是,发送主机 A 和接收主机 B 不在同一个子网中,假设一个一般场景,两台主机所在的子网由一台路由器联通。这里需要注意的是,一般情况下,我们说网络设备都有一个 IP 地址和一个 MAC 地址,这里说的网络设备,更严谨的说法应该是一个接口。路由器作为互联设备,具有多个接口,每个接口同样也应该具备不重复的 IP 地址和 MAC 地址。因此,在讨论 ARP 表时,路由器的多个接口都个各自维护一个 ARP 表,而非一个路由器只维护一个 ARP 表。
接下来,回顾同一子网内的 MAC 寻址,如果主机 A 发送一个广播问询分组,那么 A 所在子网内的所有设备(接口)都将不会捕获该分组,因为该分组的目的 IP 地址在另一个子网中,本子网内不会有设备成功接收。那么,主机 A 应该发送怎样的查询分组呢?整个过程按照时间顺序发生的事件如下:
主机 A 查询 ARP 表,期望寻找到目标路由器的本子网接口的 MAC 地址。
目标路由器指的是,根据目的主机 B 的 IP 地址,分析出 B 所在的子网,能够把报文转发到 B 所在子网的那个路由器。
主机 A 未能找到目标路由器的本子网接口的 MAC 地址,将采用 ARP 协议,问询到该 MAC 地址,由于目标接口与主机 A 在同一个子网内,该过程与同一局域网内的 MAC 寻址相同。
主机 A 获取到目标接口的 MAC 地址,先构造 IP 数据报,其中源 IP 是 A 的 IP 地址,目的 IP 地址是 B 的 IP 地址,再构造链路层帧,其中源 MAC 地址是 A 的 MAC 地址,目的 MAC 地址是本子网内与路由器连接的接口的 MAC 地址。主机 A 将把这个链路层帧,以单播的方式,发送给目标接口。
目标接口接收到了主机 A 发过来的链路层帧,解析,根据目的 IP 地址,查询转发表,将该 IP 数据报转发到与主机 B 所在子网相连的接口上。
到此,该帧已经从主机 A 所在的子网,转移到了主机 B 所在的子网了。
路由器接口查询 ARP 表,期望寻找到主机 B 的 MAC 地址。
路由器接口如未能找到主机 B 的 MAC 地址,将采用 ARP 协议,广播问询,单播响应,获取到主机 B 的 MAC 地址。
路由器接口将对 IP 数据报重新封装成链路层帧,目标 MAC 地址为主机 B 的 MAC 地址,单播发送,直到目的地。
IPV4和IPV6区别
- Pv4是32位IP地址,而IPv6是128位IP地址,彻底解决IP地址不足的问题。
- IPv4是数字地址,用点分隔。 IPv6是一个字母数字地址,用冒号分隔。
- IPv4根据提供的IP选项,有20~60个字节的可变长度;而IPv6拥有40个字节的固定长度,相对于IPv4而言报头简单。
- 对于IPv4而言,互联网安全协议(IPsec)是可选的,但不一定是免费的,有的需要付费支持;但对于IPv6来说,互联网安全协议是必选项,更加安全。
MTU和MSS分别是什么?
MTU:maximum transmission unit,最大传输单元,由硬件规定,如以太网的MTU为1500字节。
MSS:maximum segment size,最大报文段大小,为TCP数据包每次传输的最大数据分段大小,一般由发送端向对端TCP通知对端在每个分节中能发送的最大TCP数据。MSS值为MTU值减去IPv4 Header(20 Byte)和TCP header(20 Byte)得到。
网络层分片的原因与具体实现
因为在链路层中帧的大小通常都有限制,比如在以太网中帧的最大大小(MTU)就是1500字节。如果IP数据包加上头部后大小超过1500字节,就需要分片。
IP分片和完整IP报文差不多拥有相同的IP头,16位ID域对于每个分片都是一致的,这样才能在重新组装的时候识别出来自同一个IP报文的分片。在IP头里面,16位识别号唯一记录了一个IP包的ID,具有同一个ID的IP分片将会重新组装;而13位片偏移则记录了某IP片相对整个包的位置;而这两个表中间的3位标志则标志着该分片后面是否还有新的分片。这三个标志就组成了IP分片的所有信息(将在后面介绍),接受方就可以利用这些信息对IP数据进行重新组织。
什么是IP地址和MAC地址?为啥有了IP地址还需要MAC地址
- MAC地址用于唯一标识网络适配器(网卡)。
- IP地址只是逻辑上的标识,任何人都能随意修改,因此不能具体标识一个用户,但MAC地址固化在网卡里,防止被盗用。
- 但是如果只用MAC地址的话,因为MAC地址无序杂乱,没有明显规则,难以查找。但是IP是分层的,类似通讯地址,可以根据其网络号找到子网再定义主机,逐级查找,每个设备需要存储的信息较少
MAC地址与IP地址的区别
- 长度不同,IP地址一般为32位(IPv6 128位),MAC地址则是48位
- 分配依据不同,IP地址分配基于网络拓扑,能够根据需要改动设备的IP地址,但是MAC地址的分配是基于制造商,在网卡中烧录好,一般不轻易改变
- 寻址协议层不同,IP地址应用于网络层,MAC地址应用于数据链路层(数据链路层基于MAC地址转发数据帧,数据链路层的交换机根据其MAC地址记录表中的MAC地址及其对应的端口,将其发送到MAC地址对应的端口,否则广播;网络层则根据IP地址转发报文,路由器根据路由表转发到对应端口,否则发送默认路由)
IP寻址和MAC寻址有什么不同,怎么实现
通过MAC地址寻找主机是MAC地址寻址,通过IP地址寻找主机叫IP地址寻址。它们适用于不同的协议层,IP寻址是网络层,Mac寻址是数据链路层。
IP寻址的过程(ARP协议):主机A想通过IP地址寻找到目标主机,首先分析IP地址确定目标主机与自己是否为同一网段。如果是则查看ARP缓存,或者使用ARP协议发送广播。如果不是,则寻找网关发送ARP数据包。
网际控制报文协议ICMP
ICMP 是为了更有效地转发 IP 数据报和提高交付成功的机会。它封装在 IP 数据报中,但是不属于高层协议。
ICMP 报文分为差错报告报文和询问报文。
1.ping
Ping 是基于ICMP协议工作的,主要用来测试两台主机之间的连通性。
Ping 的原理是通过向目的主机发送 ICMP Echo 请求报文,目的主机收到之后会发送 Echo 回答报文。Ping 会根据时间和成功响应的次数估算出数据包往返时间以及丢包率。
2.Traceroute
Traceroute 是 ICMP 的另一个应用,用来跟踪一个分组从源点到终点的路径。
Traceroute 发送的 IP 数据报封装的是无法交付的 UDP 用户数据报,并由目的主机发送终点不可达差错报告报文。
- 源主机向目的主机发送一连串的 IP 数据报。第一个数据报 P1 的生存时间 TTL 设置为 1,当 P1 到达路径上的第一个路由器 R1 时,R1 收下它并把 TTL 减 1,此时 TTL 等于 0,R1 就把 P1 丢弃,并向源主机发送一个 ICMP 时间超过差错报告报文;
- 源主机接着发送第二个数据报 P2,并把 TTL 设置为 2。P2 先到达 R1,R1 收下后把 TTL 减 1 再转发给 R2,R2 收下后也把 TTL 减 1,由于此时 TTL 等于 0,R2 就丢弃 P2,并向源主机发送一个 ICMP 时间超过差错报文。
- 不断执行这样的步骤,直到最后一个数据报刚刚到达目的主机,主机不转发数据报,也不把 TTL 值减 1。但是因为数据报封装的是无法交付的 UDP,因此目的主机要向源主机发送 ICMP 终点不可达差错报告报文。
- 之后源主机知道了到达目的主机所经过的路由器 IP 地址以及到达每个路由器的往返时间。
虚拟专用网VPN
由于 IP 地址的紧缺,一个机构能申请到的 IP 地址数往往远小于本机构所拥有的主机数。并且一个机构并不需要把所有的主机接入到外部的互联网中,机构内的计算机可以使用仅在本机构有效的 IP 地址(专用地址)。
有三个专用地址块:
- 10.0.0.0 ~ 10.255.255.255
- 172.16.0.0 ~ 172.31.255.255
- 192.168.0.0 ~ 192.168.255.255
VPN 使用公用的互联网作为本机构各专用网之间的通信载体。专用指机构内的主机只与本机构内的其它主机通信;虚拟指好像是,而实际上并不是,它有经过公用的互联网。
下图中,场所 A 和 B 的通信经过互联网,如果场所 A 的主机 X 要和另一个场所 B 的主机 Y 通信,IP 数据报的源地址是 10.1.0.1,目的地址是 10.2.0.3。数据报先发送到与互联网相连的路由器 R1,R1 对内部数据进行加密,然后重新加上数据报的首部,源地址是路由器 R1 的全球地址 125.1.2.3,目的地址是路由器 R2 的全球地址 194.4.5.6。路由器 R2 收到数据报后将数据部分进行解密,恢复原来的数据报,此时目的地址为 10.2.0.3,就交付给 Y。
网络地址转换NAT
专用网内部的主机使用本地 IP 地址又想和互联网上的主机通信时,可以使用 NAT 来将本地 IP 转换为全球 IP。
在以前,NAT 将本地 IP 和全球 IP 一一对应,这种方式下拥有 n 个全球 IP 地址的专用网内最多只可以同时有 n 台主机接入互联网。为了更有效地利用全球 IP 地址,现在常用的 NAT 转换表把传输层的端口号也用上了,使得多个专用网内部的主机共用一个全球 IP 地址。使用端口号的 NAT 也叫做网络地址与端口转换 NAPT。
路由协议
可以把路由选择协议划分为两大类:
- 自治系统内部的路由选择:RIP 和 OSPF
- 自治系统间的路由选择:BGP
RIP:分布式的基于距离向量的路由选择协议,只适用于小型互联网。RIP按固定的时间间隔与相邻路由器交换信息,交换的信息是自己当前的路由表。
OSPF:分布式的链路状态协议,适用于大型互联网。OSPF只在链路状态发生变化时,才用向本自治系统中的所有路由器,用洪泛法发送与本路由器相邻的所有路由器的链路状态信息。
BGP:不同AS的路由器之间交换路由信息的协议,是一种路径向量路由选择协议。BGP力求寻找一条能够到达目的网络(可达)且比较好的路由(不兜圈子),而并非要寻找一条最佳路由。
路由分组转发流程
- 从数据报的首部提取目的主机的 IP 地址 D,得到目的网络地址 N。
- 若 N 就是与此路由器直接相连的某个网络地址,则进行直接交付;
- 若路由表中有目的地址为 D 的特定主机路由,则把数据报传送给表中所指明的下一跳路由器;
- 若路由表中有到达网络 N 的路由,则把数据报传送给路由表中所指明的下一跳路由器;
- 若路由表中有一个默认路由,则把数据报传送给路由表中所指明的默认路由器;
- 报告转发分组出错。
链路层
交换机
交换机具有自学习能力,学习的是交换表的内容,交换表中存储着 MAC 地址到接口的映射。
正是由于这种自学习能力,因此交换机是一种即插即用设备,不需要网络管理员手动配置交换表内容。
下图中,交换机有 4 个接口,主机 A 向主机 B 发送数据帧时,交换机把主机 A 到接口 1 的映射写入交换表中。为了发送数据帧到 B,先查交换表,此时没有主机 B 的表项,那么主机 A 就发送广播帧,主机 C 和主机 D 会丢弃该帧,主机 B 回应该帧向主机 A 发送数据包时,交换机查找交换表得到主机 A 映射的接口为 1,就发送数据帧到接口 1,同时交换机添加主机 B 到接口 2 的映射。
虚拟局域网
虚拟局域网可以建立与物理位置无关的逻辑组,只有在同一个虚拟局域网中的成员才会收到链路层广播信息。
例如下图中 (A1, A2, A3, A4) 属于一个虚拟局域网,A1 发送的广播会被 A2、A3、A4 收到,而其它站点收不到。
使用 VLAN 干线连接来建立虚拟局域网,每台交换机上的一个特殊接口被设置为干线接口,以互连 VLAN 交换机。IEEE 定义了一种扩展的以太网帧格式 802.1Q,它在标准以太网帧上加进了 4 字节首部 VLAN 标签,用于表示该帧属于哪一个虚拟局域网。