前言
本文是对最近常见的面试题做出一个汇总,有许多面试题以及对应的答案并非是本人所写,涉及摘录的文档在文章末尾已经标注,感谢诸位前辈的努力。
如果大家发现更多计算机网络相关的面试题可以补充到这里,欢迎大家留言。
一、计算机网络综述
描述一下OSI与TCP/IP各层的结构与功能?
1. 应用层
应用层(application-layer)是网络应用程序以及它们的应用层协议存留的地方。因特网的应用层包括许多协议,例如HTTP、SMTP、FTP等。我们把这种位于这种位于应用层的信息分组称为报文(message)。
2. 运输层
运输层(transport layer)的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务。应用进程利用该服务传送应用层报文。我们把这种位于这种位于应用层的信息分组称为报文段(segment)。
运输层主要使用以下两种协议:
- 传输控制协议 TCP(Transmission Control Protocol)–提供面向连接的,可靠的数据传输服务。
- 用户数据协议 UDP(User Datagram Protocol)–提供无连接的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。
3. 网络层
在 计算机网络中进行通信的两个计算机之间可能会经过很多个数据链路,也可能还要经过很多通信子网。网络层的任务就是选择合适的网间路由和交换结点, 确保数据及时传送。 在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP/IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报 ,简称 数据报(datagram)。
互联网是由大量的异构(heterogeneous)网络通过路由器(router)相互连接起来的。互联网使用的网络层协议是无连接的网际协议(Internet Protocol)和许多路由选择协议,因此互联网的网络层也叫做网际层或IP层。
4. 数据链路层
数据链路层(data link layer)通常简称为链路层。两台主机之间的数据传输,总是在一段一段的链路上传送的,这就需要使用专门的链路层的协议。 在两个相邻节点之间传送数据时,数据链路层将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。
5. 物理层
在物理层上所传送的数据单位是比特。
物理层(physical layer)的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异, 使其上面的数据链路层不必考虑网络的具体传输介质是什么。“透明传送比特流”表示经实际电路传送后的比特流没有发生变化,对传送的比特流来说,这个电路好像是看不见的。
二、HTTP相关
什么是HTTP?
HTTP是指超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。
谈一下HTTP1.0、HTTP1.1和HTTP2.0的区别
HTTP1.1
- 缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
- 带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
- 错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
- Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址与端口。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
- 长连接,HTTP 1.1支持长连接(Persistent Connection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
HTTP2.0
-
新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
-
多路复用(Multiplexing),即连接 共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
-
header压缩,HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
-
服务端推送(server push),采用了SPDY的网页,例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。
谈一下HTTP与HTTPS的区别
HTTP | HTTPS | |
---|---|---|
CA | 不需要 | 需要到CA申请证书,需要交费 |
安全性 | 运行在TCP上,明文传输 | 运行在SSL/TLS上,所有传输内容都经过加密。 所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。 |
端口 | 80 | 443 |
运营商劫持 | 不防止 | 防止 |
谈一谈HTTP报文
HTTP报文是简单的格式化数据块,由三个部分组成:起始行(start line),首部(header)以及可选的主体(body)部分。
HTTP报文可以分为两类:请求报文和响应报文,其基本报文结构相同。
-- 请求报文格式
<method> <request-URL> <version>
<headers>
<entity-boby>
-- 响应报文格式
<version> <status> <reason-phrase>
<headers>
<entity-body>
例如:
GET /pet-products.html HTTP/1.1
Host: www.joes.com
Accept: *
---------------------------------
HTTP/1.1 301 Moved Permanently
Location: http://www.gentle.com/
Content-length: 56
Content-type: text/plain
Please go to another page.
谈一谈HTTP常见的方法
方法 | 描述 | 是否包含主体? | 是否幂等 |
---|---|---|---|
GET | 从服务器获取一份文档 | 否 | 是 |
HEAD | 只从服务器获取文档的首部 | 否 | 是 |
POST | 向服务器发送需要处理的数据 | 是 | 否 |
PUT | 从客户端向服务器传送的数据取代指定的文档的内容。(全部取代) | 是 | 是 |
PATCH | 从客户端向服务器传送的数据取代指定的文档的内容。(部分取代) | 是 | 否 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断 | 否 | 是 |
OPTIONS | 决定可以在服务器上执行哪些方法 | 否 | 是 |
DELETE | 从服务器上删除一份文档 | 否 | 是 |
**HTTP幂等方法,是指无论调用这个url多少次,都不会有不同的结果的HTTP方法。也就是不管你调用1次还是调用100次,1000次,结果都是一样的
谈一谈常用的状态码
状态码 | 原因短语 | 含义 |
---|---|---|
100 | Continue | 收到请求初始部分,请客户端继续 |
101 | Switching Protocols | 服务器正在根据客户端指定,切换协议 |
200 | OK | 请求没有问题,实体的主体部分包含了所请求的资源 |
202 | Accepted | 请求已被接收,但服务器还未对其执行任何操作,不保证服务器会完成。 |
300 | Multiple Choices | 客户端请求一个实际指向多个资源的URL |
301 | Moved Permanently | 在请求的URL已被永久移除 |
302 | Found | 客户端应使用Location首部给出的URL来临时定位资源 |
400 | Bad Request | 客户端发送了一个错误的请求 |
401 | Unauthorized | 客户端访问资源前需认证 |
403 | Forbidden | 请求被服务器拒绝,服务器也不想说明为什么 |
404 | Not Found | 无法找到所请求的URL |
500 | Internal Server Error | 服务器遇到一个妨碍完成请求的错误 |
501 | Not Implemented | 客户端发起的请求超出服务范围 |
谈一谈常用的首部
Name | Type | Description |
---|---|---|
Date | 通用首部 | 提供日期和时间标志,说明报文是什么时间创建的 |
MIME-Version | 通用首部 | 给出了发送端使用的 MIME 版本 |
Update | 通用首部 | 给出了发送端可能想要“升级”使用的新版本或协议 |
Trailer | 通用首部 | 如果报文采用了分块传输编码(chunked transfer encoding)方式,就可以用这个首部列出位于报文拖挂(trailer)部分的首部集合 |
Cache-Control | 通用缓存首部 | 用于随报文传送缓存指示 |
Host | 请求首部 | 给出了接收请求的服务器的主机名和端口号 |
/ | Accept请求首部 | Accept 首部为客户端提供了一种将其喜好和能力告知服务器的方式,包括它们想 要什么,可以使用什么,以及最重要的,它们不想要什么。 |
/ | 条件请求首部 | 客户端希望为请求加上某些限制。 |
/ | 安全请求首部 | HTTP 本身就支持一种简单的机制,可以对请求进行质询 / 响应认证。这种机制要 求客户端在获取特定的资源之前,先对自身进行认证,这样就可以使事务稍微安全 一些。 |
/ | 响应首部 | |
/ | 实体首部 | 有很多首部可以用来描述 HTTP 报文的负荷。由于请求和响应报文中都可能包含实 体部分,所以在这两种类型的报文中都可能出现这些首部。 |
具体可以看以下文章:HTTP 首部字段详细介绍 - 超超boy - 博客园 (cnblogs.com)
HTTP是无状态的协议,如何保存用户状态?
HTTP 是一种不保存状态,即无状态(stateless)协议。也就是说 HTTP 协议自身不对请求和响应之间的通信状态进行保存。那么我们保存用户状态呢?Session 机制的存在就是为了解决这个问题,Session 的主要作用就是通过服务端记录用户的状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了(一般情况下,服务器会在一定时间内保存这个 Session,过了时间限制,就会销毁这个Session)。
在服务端保存 Session 的方法很多,最常用的就是内存和数据库(比如是使用内存数据库redis保存)。既然 Session 存放在服务器端,那么我们如何实现 Session 跟踪呢?大部分情况下,我们都是通过在 Cookie 中附加一个 Session ID 来方式来跟踪。
Cookie 被禁用怎么办?
最常用的就是利用 URL 重写把 Session ID 直接附加在URL路径的后面。
Cookie的作用是什么?和Session有什么区别?
Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。
Cookie 一般用来保存用户信息 比如①我们在 Cookie 中保存已经登录过得用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了;②一般的网站都会有保持登录也就是说下次你再访问网站的时候就不需要重新登录了,这是因为用户登录的时候我们可以存放了一个 Token 在 Cookie 中,下次登录的时候只需要根据 Token 值来查找用户即可(为了安全考虑,重新登录一般要将 Token 重写);③登录一次网站后访问网站其他页面不需要重新登录。
Session 的主要作用就是通过服务端记录用户的状态。 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。
Cookie 存储在客户端中,而Session存储在服务器上,相对来说 Session 安全性更高。如果要在 Cookie 中存储一些敏感信息,不要直接写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。
谈下URI、URL的区别
每个Web服务器资源都有一个名字,以方便客户端定位,这个服务器资源名被称为 统一资源标识符(URI)。URI有两种形式,分别是统一资源定位符URL(Uniform Resource Location,例如http://www.yahoo.com/images/logo.gif)与统一资源名URN(Uniform Resource Location,如urn:ietf:rfc:2141)。不过URN仍然处于试验阶段,没有大范围使用。
讲一讲浏览器访问一个网站再到服务器返回资源的流程?
(a) 浏览器从 URL 中解析出服务器的主机名;
(b) 浏览器将服务器的主机名转换成服务器的 IP 地址;
© 浏览器将端口号(如果有的话)从 URL 中解析出来;
(d) 浏览器建立一条与 Web 服务器的 TCP 连接;
(e) 浏览器向服务器发送一条 HTTP 请求报文;
(f) 服务器向浏览器回送一条 HTTP 响应报文;
(g) 关闭连接,浏览器显示文档。
聊一聊常用的提高HTTP连接性能的方法
并行连接
通过多条TCP连接发起并行的HTTP请求(缺陷:连接到较快的服务器可能抢占带宽、占用较大内存)
持久连接
重用TCP连接,以消除连接及关闭时延。HTTP/1.1(以及 HTTP/1.0 的各种增强版本)允许 HTTP 设备在事务处理结束 之后将 TCP 连接保持在打开状态,以便为未来的 HTTP 请求重用现存的连接。在事 务处理结束之后仍然保持在打开状态的 TCP 连接被称为持久连接。HTTP/1.0+Keep-alive或HTTP1.1+persistent
管道化连接
通过共享的TCP连接发起并发的HTTP请求。在响应到达之前,可以将多条请求放入队列。当第一条请求通过网络 流向地球另一端的服务器时,第二条和第三条请求也可以开始发送了。
复用的连接
交替传送请求和响应报文(实验阶段)。
介绍一下HTTPS?
HTTP是最常见的HTTP安全版本,本质就是在安全的传输层上发送的HTTP。
https工作流程
- 客户端与服务器建立端口为443的TCP连接
- 客户端与服务端进行SSL握手,交换协议版本号、密码以及会话密钥
- 在SSL上传输已加密的请求
- 关闭SSL连接
- 关闭TCP连接
SSL握手流程
HTTPS 的优缺点?
优点:
可靠性高,安全性高,避免数据在传输过程中被窃取、改变以及拦截
缺点:
SSL握手阶段耗时,性能略低;连接缓存低效;SSL证书需要较高成本。
介绍下DNS工作流程?
DNS(DOMAIN NAME SYSTEM)是一个域名系统,是万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。
第一步:客户机提出域名解析请求,并将该请求发送给本地 域名服务器。
第二步:当本地 域名服务器收到请求后,就先查询本地 缓存,如果 该纪录项,则本地 域名服务器就直接把查询 结果返回。
第三步:如果本地 缓存中没 该纪录,则本地域名服务器就直接把请求发给根域名服务器,然后根域名服务器再返回给本地域名服务器一个所查询域(根 子域) 主域名服务器 地址。
第四步:本地服务器再向 一步返回 域名服务器发送请求,然后接受请求 服务器查询自己 缓存,如果没 该纪录,则返回相关 下级 域名服务器 地址。
第五步:重复第四步,直到找到正确 纪录。
第六步:本地域名服务器把返回 结果保存到缓存,以备下一次使用,同时还将结果返回给客户机。
三、TCP/UDP相关
TCP是什么?
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP的报文格式一般是什么样的?
聊一聊套接字工作流程?
TCP 三次握手
为什么采用三次握手,而不是一次/两次?
通过三次握手,可以使服务器与客户端同时知晓自身的发送、接收以及对方的发送、接收功能都是正常的;同时,如果只有两次握手,可能会发生死锁。在第二次握手中,如果客户端没有接收到服务器的应答分组,无法得知服务器是否准备就绪,将会忽略所有来自服务器的分组(服务器认为自己准备就绪了),不会返回ACK,服务器就会在超时后,重发分组,形成了死锁。
TCP 四次挥手
为什么采用四次挥手,而不是三次?
因为TCP网络是全双工的通信协议。一方发出FIN信号只能代表这个方向的数据已经全部发送完毕,而另一方是否仍有数据需要发送是不知道的,因此需要四次挥手。
TCP与UDP 协议的区别
TCP | UDP |
---|---|
面向连接 | 无连接 |
可靠 | 不可靠 |
传输数据有序 | 不保证有序 |
不保存数据边界 | 保存边界 |
速率略慢 | 速率略快 |
拥有流量控制和拥塞控制 | 无 |
首部较长,20字节 | 首部较短,8字节 |
不可以广播、多播 | 支持广播、多播 |
常用于邮件、网页等需要可靠传输的场景 | 常用于直播、视频或DNS等协议 |
TCP 协议如何保证可靠传输
- TCP数据编号与确认。TCP的确认是对接收到的数据的最高序号表示确认。接收端返回的确认号是已经收到的序号+1。
- TCP重传机制。TCP每发送一个报文段,就对这个报文段设置计时器。只要计时器到了规定时间还未收到确认,则需重传。
- 数据包校验机制:如果数据包在传输过程中发生任何错误,则会丢弃此数据包。
- 流量控制机制:TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。TCP常使用的是可变大小的滑动窗口协议。
什么是TCP拆包/粘包,一般如何解决?
采用TCP协议发送数据时,经常是一个长连接的状态。当发送的数据包过小时,TCP协议默认启用Nagle算法,将较小的数据包合并发送,导致粘包。同时,接收方由于接受到的数据都会优先放入缓冲区,也有可能造成读取粘包问题。
解决方案:
- 在包头首部增加数据包的长度。
- 使用特殊字符作为分隔符。
为什么 TIME-WAIT 状态必须等待 2MSL 的时间?
1、为了保证A发送的最后一个 ACK 报文段能够到达 B。这个 ACK 报文段有可能丢失,因而使处在 LAST-ACK 状态的 B 收不到对已发送的 FIN + ACK 报文段的确认。B会超时重传这个 FIN+ACK 报文段,而 A 就能在 2MSL 时间内(超时 + 1MSL 传输)收到这个重传的 FIN+ACK 报文段。接着 A 重传一次确认,重新启动 2MSL 计时器。最后,A 和 B 都正常进入到 CLOSED 状态。如果 A 在 TIME-WAIT 状态不等待一段时间,而是在发送完 ACK 报文段后立即释放连接,那么就无法收到 B 重传的 FIN + ACK 报文段,因而也不会再发送一次确认报文段,这样,B 就无法按照正常步骤进入 CLOSED 状态。
2、 防止已失效的连接请求报文段出现在本连接中。A 在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。
TIME_WAIT 状态会导致什么问题,怎么解决?
在高并发短连接的 TCP 服务器上,当服务器处理完请求后主动请求关闭连接,这样服务器上会有大量的连接处于 TIME_WAIT 状态,服务器维护每一个连接需要一个 socket,也就是每个连接会占用一个文件描述符,而文件描述符的使用是有上限的,如果持续高并发,会导致一些正常的连接失败。
解决方案:修改配置或设置 SO_REUSEADDR 套接字,使得服务器处于 TIME-WAIT 状态下的端口能够快速回收和重用。
UDP如何实现可靠传输?
这道题可以参考TCP可靠传输的方式。
- 增加seq/ack机制
- 设置发送和接收缓冲区
- 添加超时重传机制
TCP 最大连接数限制
client最大tcp连接数
client每次发起tcp连接请求时,除非绑定端口,通常会让系统选取一个空闲的本地端口(local port),该端口是独占的,不能和其他tcp连接共享。tcp端口的数据类型是unsigned short,因此本地端口个数最大只有65536,端口0有特殊含义,不能使用,这样可用端口最多只有65535,所以在全部作为client端的情况下,最大tcp连接数为65535,这些连接可以连到不同的server ip。
server最大tcp连接数
server通常固定在某个本地端口上监听,等待client的连接请求。不考虑地址重用(unix的SO_REUSEADDR选项)的情况下,即使server端有多个ip,本地监听端口也是独占的,因此server端tcp连接4元组中只有remote ip(也就是client ip)和remote port(客户端port)是可变的,因此最大tcp连接为客户端ip数×客户端port数,对IPV4,不考虑ip地址分类等因素,最大tcp连接数约为2的32次方(ip数)×2的16次方(port数),也就是server端单机最大tcp连接数约为2的48次方。
实际的tcp连接数
上面给出的是理论上的单机最大连接数,在实际环境中,受到机器资源、操作系统等的限制,特别是sever端,其最大并发tcp连接数远不能达到理论上限。在unix/linux下限制连接数的主要因素是内存和允许的文件描述符个数(每个tcp连接都要占用一定内存,每个socket就是一个文件描述符),另外1024以下的端口通常为保留端口。在默认2.6内核配置下,经过试验,每个socket占用内存在15~20k之间。