Network 常见面试题目

套接字

套接字是一个同一台主机内应用层和网络层之间的接口。由于套接字是在网络上建立网络应用程序的可编程接口,所以也把套接字称为应用程序和网络之间的应用编程接口。

一个UDP套接字是由目的IP地址和目的端口号标识的二元组。两个UDP报文段,只要目的IP地址和目的端口号一样,不论源IP地址和端口号是否一样,都被定向到相同的目的进程。
一个TCP套接字是由源IP地址,源端口号,目的IP地址,目的端口号构成的四元组。所有的这四元组都被用来进行多路分解。

常见应用层协议

DNS
FTP
HTTP
SMTP

HTTP

HTTP请求报文段

HTTP包含一行请求行和多行首部行。
请求行有三个字段:方法字段,URL字段,HTTP协议版本字段。
方法字段有GET,POST,HEAD,PUT和DELETE。

  1. Host,目标主机。
  2. Connection,浏览器告诉服务器不希望使用持久连接。
  3. User-agent,浏览器。
  4. Accept-language

HTTP响应报文段

一个状态行和6个首部行,然后是报文实体。
状态行:
协议版本,状态码和相应状态信息。
6个首部行:

  1. Connection,不适用持久链接。
  2. Date,服务器产生发送报文的时间。
  3. Server,服务器类型。
  4. Last-Modified,对象创建或者修改的最后日期。
  5. Content-Length,发送内容的长度。
  6. Content Type,发送内容的类型。

HTTP状态码[3,4, 5]

1xx信息
2xx成功
200 OK 请求成功
201 Created 当服务器按照客户端的的请求创建了一个新的资源时,发送此响应代码。
204 No Content。服务端拒绝对PUT,POST或者DELETE请求返回任何状态信息。返回空文件替换缓存。而304是使用上次的缓存。
3xx 重定向,客户端需要做一些额外的工作才能得到所需要的资源,他们通过用于GET请求。
301 Moved Permanently 服务器知道客户端请求的资源,但是不喜欢客户端使用当前URL。
302 Found。临时性重定向。不是永久性移动,而是临时性移动。比如说用户把uri保存为书签,出现301时,书签会被更新,出现302时不会。。
303 See Other。请求已经被处理,但是服务器返回的不是文档,是一个URI。和302功能一样,但是303明确表示客户端应该使用GET方法获取资源。
304 Not modified。客户端有数据主题,不需要重复发送。
307 Temporary Redict。临时性重定向,和302有着相同的意思。但是不会将POST修改成GET。
301,302,303响应状态码返回时,几乎所有的浏览器都会把POST改成GET,删除请求体,再次发送请求。尽管301,302是禁止将POST改成GET的,但是大家都会这么做。
4xx表示客户端错误
400 Bad Request,服务器收到了请求,但是不知道什么意思。
401 请求要求用户的身份认证,而客户端认证失败。
403 客户端的请求正确,但是服务端拒绝此请求,暗示了请求的资源确实存在。
404 Not Found,服务器无法把客户端请求的URI转换为一个资源。
405 客户端中请求的方法被禁止
5xx表示服务器错误
500 Internal Server Error对于大多数web框架,如果在执行请求处理代码时遇到了异常,就发送此代码。
502 bad gateway
503 Service Unavaiable,服务器当前不能处理处理客户端的请求,可能一会就好了。
505 HTTP Version Not Support

GET和POST区别

  1. GET是安全的,POST是不安全的。
  2. GET是幂等的,POST是不幂等的。
  3. GET是可缓存的,POST通常是不可缓存的。

GET一般是请求服务器的指定资源,是安全,幂等,可缓存的。而post一般是根据请求的payload对指定的资源机械能给你处理,POST是不安全的,不幂等的,不可缓存的。

其他:

  1. GET会把请求的数据会放在URL后面,而POST把请求的数据放在body中。注意,GET的body也可以存放request body,这是针对于接口来说的。
  2. GET请求提交的url数据最多是1024字节是浏览器或者服务器限制的,而post则没有限制。
  3. GET和POST都不安全,HTTP本身是明文协议,无论是url,header还是body,都是在网络中明文传播的。只不过url中的数据是可以在浏览器中直接看到的,而header和body中的数据更麻烦一些,需要使用抓包软件查看。
  4. 但是GET的效率要比post高。

HTTPS和HTTP[2]

HTTP协议是明文协议,TCP和UDP也没有加密。于是就有了SSL,利用非对称密码体系对发送的数据进行加密。
HTTPS是在TCP连接之后由客户端发起的。其实使用到了对称加密技术和非对称加密技术。

  1. 客户端发送一个Client Hello给服务器,包含一个随机数,以及客户端支持的加密条件和SSL版本。
  2. 服务端回应一个Server Hello给客户端,服务器选定一组加密套件,然后和第二个随机数,以及服务器的证书(包含服务器的公钥和名字)一块发送给客户端。服务器是由CA机构发送到,一个大家都信任的机构。
  3. 客户端验证服务端的证书的真实性。(使用CA的数字证书,服务端的证书含有CA对服务器信息的签名,然后客户端使用CA证书中的公钥对服务端的数字证书进行验证签名,验证签名即使用相同的摘要算法对服务器的信息进行摘要,然后和CA证书的签名对比。)
    验证成功之后,生成第三个随机数,使用服务端的公钥对这个随机数加密生成PreMaster Key,然后发送给服务端。
  4. 服务端用自己的私钥解密生成PreMaster Key。这个时候,两边都拥有三个随机数,使用相同的算法生成一个秘钥。之后的通信都使用这个秘钥进行。

输入www.baidu.com发生的一切

  1. 用户输入网址。
  2. DNS解析。一般情况下,本机是会知道DNS服务器的IP地址的。递归查询和迭代查询获得目的主机的IP地址。一般是在同一个局域网内,通过ARP请求,查询对应的DNS服务器的MAC地址,然后把请求包发给它。[8]
  3. TCP连接。三次握手。
  4. 发送请求。
  5. 接收HTTP相应报文
  6. 浏览器渲染。

Cookie用户和服务器的交互。因为HTTP是无状态的,简化了服务器的设计。当想要识别用户的时候,可能限制用户的访问或者想把用户和内容关联起来。HTTP使用了cookie:
cookie有四个部分:

  1. HTTP响应报文中有一个cookie首部行。
  2. HTTP请求报文中有一个cookie首部行。
  3. 用户端系统有保留一个cookie文件。
  4. Web站点后台有一个cookie数据库。

Web缓存

Web缓存器也叫代理服务器,它有自己的磁盘存储空间,并在自己的磁盘存储空间中保存最近请求过的对象拷贝。
然后可以配置浏览器,将用户的所有HTTP请求首先指向Web缓存器,一旦配置了浏览器,每个浏览器对象的请求首先被定向到Web缓存器。

  1. 浏览器建立一个到Web缓存器的TCP连接,并发送一个HTTP请求。
  2. Web缓存器检查缓存是命中。
  3. 命中的话,Web缓存器向发送一个条件GET,查询Last-modified。
  4. 没有命中的话,Web缓存器请求该对象,并将其缓存。
  5. Web缓存器向客户机浏览器发送报文。

TCP和UDP的选择

DNS通常采用UDP,因为TCP需要建立连接,会引入建立TCP连接的时延,这样子会慢得多。如果没有收到响应,就会向另一台DNS服务器发送查询,或者通知调用的程序它不能获得响应。[9]
而HTTP使用TCP而不是UDP,因为web网页需要的是可靠性。

UDP

UDP相对于TCP的优势:

  1. 应用层能更好的控制要发送的数据和发送时间。
  2. 无需连接建立。
  3. 无连接状态。
  4. 分组首部开销小。TCP报文段有20字节的首部开销,而UDP只有8字节的开销。

UDP报文段结构

UDP报文段的首部共8个字节,64位,每个字段8位,共4个字段,:

  1. 16位源端口号
  2. 16位目的端口号
  3. 16位长度字段,长度字段包含了首部在内的UDP报文段的长度(以字节为单位)。
  4. 16位检验和

UDP校验和

  1. UDP校验和提供了差错检测功能,但是不能进行差错恢复。为什么UDP校验和work?
  2. 为什么要进行差错校验?链路中可能出错,内存中也可能出错。UDP必须在端到端基础上在运输层提供差错校验。
  3. 出错后如何处理。一些实现是丢弃受损的报文段,一些是将受损的报文段交给应用程序并告警。

可靠数据传输原理

停止等待协议

为了解决分组可能出错的情况,引入自动重传请求。自动重传请求协议需要另外三种协议:差错检验,接收方反馈和重传。
当一个分组到达时可能出错,接收方进行进行差错校验,如果出错,发送一个NAK给发送方。如果没有失败,发送一个ACK给接收方。
直到发送方确定接收方已经收到当前分组之后(收到一个ACK),才会继续发送新数据,这就是停止等待协议。如果收到一个NAK,就会重传当前分组。(接收方反馈
但是ACK和NAK也可能出错或者丢失,通过引入重传解决这个问题。
到底什么时候重传呢?等待一个RTT太久了,可以使用一个定时器设置一个时间,超过这个时间就重传。
这样子在接收方引入了冗余分组的问题。冗余分组的问题在于不知道接收方发送的ACK或者NAK是否被发送方接收,或者是分组没有丢失,等到了一段时间又到了。接收方不知道接收到的分组到底是哪一个,是重发的分组还是新的分组。可以通过引入分组序号解决这个问题。在停止等待协议中,一个比特的分组序号就够了。所以也叫比特交替协议

流水线可靠数据传输协议

停止等待协议的效率太低了。流水线可靠数据传输协议不是一次只发一个分组,而是一次发送多个分组,就好像一条流水线一样。这就产生了几个问题:

  1. 必须增加序号范围,原来只要一个比特就够了,现在需要多个。
  2. 协议的发送方和接收方也必须能够缓存多个分组。
  3. 流水线中如果分组丢失了,有两种方式进行差错恢复,回退N步(GBN)和选择重传(SR)。

回退N步

GBN的发送方要处理是三个工作,准备N个分组,处理接收方返回的ACK,以及超时重传。
GBN的接收方要处理的工作,只有接收到的分组的序号和上一次相同,会返回给发送方一个ACK,GBN采用累计确认(对序号n的分组的确认表明接收方已经正确接收到n以及n之前的分组了)。所有其他情况,都会丢弃分组。比如失序分组,接收方应该接收序号为n的分组,但是收到了序号为n+1的分组,就会丢弃,而不是缓存。

GBN维护一个大小为N的窗口。对于发送方,维护一个大小为N的窗口,如果这N个分组的ACK都没有收到,就不会发送新的数据,等待接收方返回ACK。发送方还有超时设置,(发送方发送的分组丢了,或者接收方返回的ACK丢了),都会重传。

选择重传

GBN有时候会效率太低,因为一个分组丢失,可能导致重传整个N个分组。选择重传可以用来解决这种问题。

TCP

TCP累计确认和GBN,选择重传之间的关系

GBN是滑动窗口协议,虽然也提供累计确认,但是它不会缓存失序报文,会把它们全部丢弃。假设序号为n的报文段丢失了,然后需要发送方重传n之后的所有报文。而TCP的发送方至多只会重传一个报文段,如果TCP接收方接收到了
选择重传对失序报文进行缓存,但是没有提供累计确认。

可靠数据传输

TCP发送方有三个与发送和重传有关的主要事件:

  1. 数据处理。TCP从发送缓存重拿数据,加上TCP首部,传递给IP层。然后传递给网络,TCP接收方的接收缓存获取数据。
  2. 超时。
    通过重传引发超时的报文响应超时时间。如果多次超时的话,就倍增超时时间间隔。
    冗余ACK触发快速重传(为什么发送方收到三个冗余ACK就立即快重传)。冗余ACK是对按序接收到的最后一个字节数据进行重复确认。
  3. ACK处理。如果收到的ACK是窗口的最小未确认序号,那么修改窗口的最小未确认序号。

三次握手

  1. A向B发送一个SYN报文段,并且包含自己的初始序列号。
  2. B向A发送一个SYNACK报文段,并且包含自己的初始序列号。同时分配连接缓存,变量等。
  3. A向B发送一个ACK报文段,不是SYN报文段。

为什么要随机初始化一个报文段序号

减少上次TCP连接中的报文段被当做两台主机之间新的TCP连接中的报文段。

为什么是三次握手而不是两次或者四次

其实是四次挥手,只不过第二次和第三次可以合并起来了。三次挥手的目的是确立TCP双方都能获得对方的初始序号。
为什么不是两次?如果A向B发送一个请求,B回应一个请求。而B的回应丢了,A就无法和B进行通信。如果设计成A重传,那么可能会建立很多个连接。如果设计成B重传,为什么要B重传?不是两次握手吗?他怎么知道要重传。这些都是如果设计成两次握手需要考虑的问题。
对于三次握手来说,如果

  1. A发给B的丢了,A超时重传。
  2. B发给A的丢了,B超时重传。B分配缓存,变量等。
  3. A又发给B的丢了,这时候B已经认为建立了连接。
    如果双方都没有数据,那么会触发第二步的超时重传。
    如果A要发送数据,那么A会直接把数据发给B,就肯定建立连接了。
    如果B要发送数据,也会触发第二步的超时重传。

四次挥手

  1. A发给B FIN报文段。A执行主动关闭。
  2. B发给A ACK。B进行WAIT-TIME。等待B终止连接,这个时候B可以给A发送数据,但是A不能给B发送数据。B执行被动关闭,B处于CLOSE_WAIT状态。
  3. B发给A FIN报文段。A收到报文段之后处于TIME_WAIT状态。
  4. A发给B ACK。这个时候A要等待30s或者1分钟,两分钟。因为需要确认B那边收到了ACK,否则的话,B就无法关闭。

流量控制

TCP通过让发送方维护一个16位的接收窗口(是接收方的)的变量来提供流量控制。不正式的说,接收窗口用于告诉发送方,接收方还有多少可用的缓存空间。TCP是全双工的,两端都维护一个接收窗口。
接收方将自己的缓冲区大小填入TCP首部的窗口长度字段。这个字段是多少:缓冲区的大小 - (缓冲区中的最后一个字节编号 - 从缓冲区中读出的最后一个字节)。
如果接收方窗口大小为0怎么办?这时发送方不给接收方发报文,而接收方也不发,只有在有数据或者ACK要发的时候,接收方才会给发送方发报文。随着接收方应用程序从缓冲区取走数据,发送方也不能继续发数据。这个时候怎么办?规定:当接收方的接收窗口大小为0时,发送方会不断发送含有一个数据字节的报文段。

为什么要有流量控制,为了防止快速的发送设备发出的数据过多,导致慢速的接收设备处理不过来,而发生大量数据的丢失。

拥塞控制

分组重传是网络拥塞的征兆,却不能解决网络拥塞问题。
什么时候知道出现了拥塞:

  1. 超时
  2. 收到3个冗余ACK。

为什么要有拥塞控制:

慢启动。
快恢复。收到三个ACK以后的方式叫做快恢复。
快重传。

开始时,指数方式增加,收到超时ACK时开始线性增乘性减。
但是如果发生超时,执行慢开始,即将拥塞窗口变为1MSS,然后指数速度增加,直到遇到超时事件的一半窗口值,开始线性增加。通过设置一个阈值来实现。

TIMEWAIT过多[6]

修改内核设置:

  1. 开启内核中TCP重用。
  2. 开启内核中TCP中快速回收。
  3. 修改TIMEOUT

CLOST_WAIT太多[7]

比如说一个爬虫服务器,爬取其他服务器上的内容,如果没有相应的内容,对方会断开连接,这时候爬虫服务器上的程序是被动断开,如果没有执行close引发第三次挥手,就会有很多CLOSE_WAIT。

long fat network

高带宽和长时延网络情况,被称为长肥网络。带宽和时延的乘积表示网络通道的容量,也就是能够在网络中缓冲的数据量,显然增加带宽和时延都增加在网络中缓冲的数据量。但是随着它们乘积的不断变大,TCP的局限就开始显露出来。常规的窗口大小是16位的,能接收和发送的最大大小为65535,而BDP远大于这个值。TCP就不得不发送一会数据就等待ACK,极端情况下有点像停止等待协议。
缺点

  1. 窗口小,序号少,无法充分利用带宽。窗口扩展项。
  2. 时延长。快重传。
  3. 序号用的很快。PAWS算法。
  4. RTT比较难测量。引入时间戳。

TCP和UDP的区别

  1. TCP面向连接,UDP无连接。
  2. TCP提供可靠数据传输,UDP提供不可靠数据传输。
  3. TCP的逻辑通信信道是全双工的可靠信道,而UDP是不可靠信道。
  4. TCP面向字节流,把数据看成一个无结构但是有序的字节流。UDP面向报文段。
  5. TCP有流量控制,拥塞控制,UDP无。
  6. TCP很慢,而UDP很快。
  7. TCP首部20个字节,UDP是8个字节。

Dos攻击

Dos(拒绝服务)攻击是一种宽泛类型的攻击,可以分为三类:

  • 弱点攻击
  • 带宽洪泛。攻击者向目的主机发送大量的分组,导致目标的介入链路变得非常拥塞,使得合法的分组无法到达服务器。
  • 连接洪泛。创建大量的全开或者半开TCP连接。

DDos攻击,分布式拒绝服务攻击。

SYN洪泛攻击

攻击者发送大量的SYN报文段,而不完成TCP握手的第三步,服务器不断地为这些半开连接服务器分配资源,导致服务器资源被迅速消耗。
怎么预防?SYN cookies,当服务器收到一个TCP连接时,不生成一个TCP半开连接,只生成一个初始序列号(精心计算的序列号,被称为cookie),然后发送这种序列号的SYNACK报文段。
如果客户机是合法的,客户机返回一个ACK,服务器收到ACK。然后利用这个ACK计算一个,这个ACK是否对应客户机发送的SYN报文段,如果是,生成一个全开的连接。

DNS攻击

DDos带宽洪泛攻击。攻击者向多个DNS根服务器发送大量的分组,使得大多数合法的DNS请求得不到回答。比如发送大量的ICMP报文。
怎么预防?分组过滤器,过滤ICMP报文。还有就是本地DNS服务器缓存了顶级域名服务器的地址。使得请求绕过了DNS根服务器。

传输层协议

TCP协议。
UDP协议。
运输层协议是在端系统而不是网络路由器中实现的。
端口号。
socket?

网络层协议

IP协议,IP协议为主机之间提供了逻辑通信,它的服务模型是尽力而为交互服务。
ICMP协议。互联网控制消息协议。最典型的应用是差错报告。ICMP报文有一个类型字段和一个编码字段,并且包含由该ICMP报文首次生成的IP数据报的首部和前8字节内容,以便于发送方能够确定引发该差错的数据报。
ping程序发送一个ICMP类型为8编码为0的报文到指定主机(表示回显请求),看到该回显请求的目的主机发送一个类型0编码为0的报文回显回答。
traceroute原理。traceroute利用ICMP报文实现,源主机中的该程序向目的主机发送一系列普通的IP数据报,每一个数据报都携带了一个具有不可达UDP端口号的UDP报文段,第i个报文段的TTL(time to live,确保数据报不会永远在网络中循环,每过一个路由器,字段值减一)是i。同时,源主机为每个数据报启动定时器,当第i个数据报到达第i个路由器时,TTL为0。根据IP协议的规则,路由器会向源主机发送一个ICMP告警报文(类型为11,编码为0)。该告警报文含有路由器的名字和IP地址,该ICMP报文到达源主机时,源主机从定时器得到RTT,从ICMP报文得到路由器名字和IP地址。那么什么时候停止发送数据报?当其中一个报文到达目的主机的时候,由于数据报包含了一个不可达的端口,所以目的主机会发送类型为3,编码为3的目的端口不可达的ICMP报文。
IGMP协议。网际组管理协议。用于多播。
ARP协议,地址解析协议。是算在链路层还是网络层?把IPv4地址转换成硬件地址。
RARP协议,反向地址解析协议。把硬件地址映射成IPv4地址。
路由器属于网络层设备,它只检查网络层字段。
IP地址。

MTU(最大传输单元),以太网的MTU是1500字节。IPV4要求最小MTU是68字节(20字节首部长度和40字节选项,以及8字节的偏移)。IPV6要求的最小MTU是1280字节。两个主机路径上的最小MTU称为路径MTU。路径MTU可以不对称。
当IP数据报的大小超过链路MTU时,执行分片。
最小重组缓冲区是IPV4(6)的任何实现都必须保证支持的最小数据报大小,IPV4是576字节,IPV6是1500字节。超过这个大小,就不一定能被接收方识别。所以,使用UDP的网络应用的报文段一般都不超过这个大小。
MSS(最大报文段)是用来通过对方,自己这面能够接收的最大TCP报文段大小,也就是最小重组缓冲区的实际值。MSS的大小通常设置为MTU减去IP和TCP首部的长度。

如果

数据链路层

成帧,透明传输,差错检测。
MAC地址。
交换机,网桥。
MAC地址。

物理层

集线器,中继器。

TCP“粘包”问题

粘包问题实际上不是TCP的,它是开发者在设计应用数据传输时的数据结构没有设计好好,可能两个不同的应用层数据在同一个TCP报文段中发给了接收方。
怎么解决,需要在传输层的数据流中给出边界,然后对传输层的数据流进行解析得到相应的数据。不应该依赖于socket的缓冲区作为数据报的边界。

参考文献

1.《计算机网络自顶向下》
2.https://segmentfault.com/a/1190000016855991
3.https://www.cnblogs.com/xflonga/p/9368993.html
4.https://www.cnblogs.com/aliwa/p/8495014.html
5.https://blog.csdn.net/qq_39816673/article/details/89611936
6.https://www.cnblogs.com/dadonggg/p/8778318.html
7.http://www.httpclient.cn/archives/106.html
8.https://www.cnblogs.com/lolau/p/8137541.html
9.为什么DNS使用UDP而不是TCP? - 车小胖的回答 - 知乎
https://www.zhihu.com/question/310145373/answer/583869215