网络基础 TCP / IP
通常使用的网络(包括互联网)是在 TCP / IP 协议族的基础上运作的,而 HTTP 属于它内部的一个子集。Web 使用一种名为 HTTP(HyperText Transfer Protocol,超文本传输协议)的协议作为规范,完成从客户端(指通过发送请求获取服务器资源的 Web 浏览器等)到服务器端等一系列运作流程,而协议是指规则的约定。可以说,Web 是建立在 HTTP 协议上通信的。
协议
计算机与网络设备要相互通信,双方就必须基于相同的方法。比如,探测到通信目标、由哪一边先发起通信、使用哪种语言进行通信、怎样结束通信等规则都需要事先确定。不同的硬件、操作系统之间的通信,所有的这一切都需要一种规则,而我们就把这种规则称为协议。
TCP / IP 协议族
像这样把与互联网相关联的协议集合起来总称为 TCP / IP,如 HTTP、FTP、DNS、TCP 都为 TCP / IP 协议集合下的协议。
OSI与TCP/IP分层模型
TCP / IP 协议族里最重要的一点就是分层,分层的好处是只需把各层之间的接口部分规划好,每个层次的内部设计就能*改动,而不会影响到整体。TCP / IP 协议族按层次分别为以下四层:
- 应用层,决定了向用户提供应用服务时通信的活动。 TCP / IP 协议族内预存了各类通用的应用服务,比如,FTP(File Transfer Protocol,文件传输协议)和 DNS(Domain Name System,域名系统)服务就是其中两类,HTTP 协议也处于该层;
- 传输层,对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。 在传输层有两个性质不同的协议:TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Data Protocol,用户数据报协议);
- 网络层(又名网络互连层),用来处理在网络上流动的数据包。 数据包是网络传输的最小数据单位,该层规定了通过怎样的路径(所谓的传输路线)到达对象计算机,并把数据包传送给对方。与对方计算机之间通过多台计算机或网络设备进行传输时,网络层起的作用就是在众多的选项内选择一条传输路线;
- 数据链路层(又名数据链路层,网络接口层),用来处理连接网络的硬件部分. 包括控制操作系统、硬件的设备驱动、NIC(Network Interface Card,网络适配器,即网卡),及光纤等物理可见部分(还包括连接器等一切传输媒介)。硬件上的范畴均在链路层的作用范围之内。
TCP / IP 通信传输流
利用 TCP / IP 协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则往应用层往上走。举例用 HTTP 来说明:
- 首先作为发送端的客户端在应用层(HTTP 协议)发出一个想看某个 Web 页面的 HTTP 请求;
- 接着,为了传输方便,在传输层(TCP 协议)把从应用层处收到的数据(HTTP 请求报文)进行分割,并在各个报文上打上标记序号及端口号后转发给网络层;
- 在网络层(IP 协议),增加作为通信目的地的 MAC 地址后转发给链路层;
- 这样一来,发往网络的通信请求就准备齐全了。接收端的服务器在链路层接收到数据,按序往上层发送,一直到应用层。当传输到应用层,才能算真正接收到由客户端发送过来的 HTTP请求。
发送端在层与层之间传输数据时,每经过一层时必定会被打上一个该层所属的首部信息。反之,接收端在层与层传输数据时,每经过一层时会把对应的首部消去。这种把数据信息包装起来的做法称为封装(encapsulate)。
OSI参考模型分层说明
OSI参考模型通信过程
- 1、打包数据时,每一层在处理上一层传过来的数据时,会在数据上附上当前层的首部信息后传给下一层;
- 2、解包数据时,每一层在处理下一层传过来的数据时,会将当前层的首部信息与数据分开,将数据传给上一层。
- 3、数据通信过程:
分层 | 每层的操作 |
---|---|
应用层 | 在数据前面加首部,首部包括数据内容、源地址和目标地址,同时也会处理异常的反馈信息。 |
表示层 | 将特有的数据格式转换为通用的数据格式,同时也会加上表示层的首部信息以供解析。 |
会话层 | 对何时连接,以何种方式连接,连接多久,何时断开等做记录。同时也会加会话层的首部信息。 |
传输层 | 建立连接,断开连接,确认数据是否发送成功和执行失败重发任务。 |
网络层 | 负责将数据发到目标地址,也包含首部信息。 |
数据链路层 | 通过物理的传输介质实现数据的传输。 |
物理层 | 将0/1转换成物理的传输介质,通过MAC地址进行传输。 |
与 HTTP 关系密切的协议 : IP、TCP 和 DNS
- 负责传输的 IP 协议,通过 IP 地址和 MAC 地址将数据送往对方。 按层次分,IP(Internet Protocol)网际协议位于网络层。TCP / IP 协议族中的 IP 指的是网际协议,是一种协议的名称。IP 协议的作用是把各种数据包传送给对方。而要保证确实传送到对方那里,则需要满足各类条件。其中两个重要的条件是 IP 地址和 MAC 地址(Media Access Control Address)。IP 地址指明了节点被分配到的地址,MAC 地址是指网卡所属的固定地址。IP 地址可以和 MAC 地址进行配对。IP 地址可变换,但 MAC 地址基本上不会更改。在网络上,通信的双方通常是经过多台计算机和网络设备中转才能连接到对方。而在进行中转时,会利用下一站中转设备的 MAC 地址来搜索下一个中转目标。这时,会采用 ARP 协议(Address Resolution Protocol),一种用以解析地址的协议,根据通信方的 IP 地址就可以反查出对应的 MAC 地址。在到达通信目标前的中转过程中,那些计算机和路由器等网络设备只能获悉很粗略的传输路线,这种机制称为路由选择(routing);
- 确保可靠性的 TCP 协议,使用了三次握手策略确保数据发送成功。 按层次分,TCP 位于传输层,提供可靠的字节流服务。所谓的字节流服务(Byte Stream Service)是指,为了方便传输,将大块数据分割成以报文段(segment)为单位的数据包进行管理。而可靠的传输服务是指,能够把数据准确可靠地传给对方。即 TCP 协议为了更容易传送大数据才把数据分割,而且 TCP 协议采用三次握手策略。
简单示意图:
- 客户端–发送带有 SYN 标志的数据包–一次握手–服务端
- 服务端–发送带有 SYN/ACK 标志的数据包–二次握手–客户端
- 客户端–发送带有带有 ACK 标志的数据包–三次握手–服务端
-
四次挥手
断开一个 TCP 连接则需要“四次挥手”:
- 客户端-发送一个 FIN,用来关闭客户端到服务器的数据传送
- 服务器-收到这个 FIN,它发回一 个 ACK,确认序号为收到的序号加1 。和 SYN 一样,一个 FIN 将占用一个序号
- 服务器-关闭与客户端的连接,发送一个FIN给客户端
- 客户端-发回 ACK 报文确认,并将确认序号设置为收到序号加1
- 负责域名解析的 DNS 服务,提供域名到 IP 地址之间的解析服务。 DNS(Domain Name System)服务是和 HTTP 协议一样位于应用层的协议,它提供域名到 IP 地址之间的解析服务。计算机既可以被赋予 IP 地址,也可以被赋予主机名和域名。用户通常使用主机名或域名来访问对方的计算机,DNS 协议提供通过域名查找 IP 地址,发送给计算机的是 IP 地址。计算机可通过 DNS 协议的逆向从 IP 地址反查域名。
概括下请求响应的流程:
- 客户端发起请求,想访问某个主机名或域名;
- DNS 协议对主机名或域名进行解析,得到 IP 地址;
- HTTP 协议将请求报文分割成多个报文段来发送;
- IP 协议通过 IP 地址和 MAC 地址将数据送往对方;
- TCP 协议使用三次握手策略确保数据发送成功,按序号以原来的顺序重组请求报文;
- 服务端获得请求报文,进行处理,处理结果同样使用 TCP / IP 协议进行回传。
URI 和 URL
URL(Uniform Resource Locator,统一资源定位符),使用 Web 浏览器等访问 Web 页面时需要输入的网页地址,比如 https://www.google.com/ 。URI 是 Uniform Resource Identifier 的缩写,这三个单词分别表示:
- Uniform,规定统一的格式可方便处理多种不同类型的资源,而不用根据上下文环境来识别资源指定的访问方式。另外,加入新增的协议方案(如 http: 或 ftp:)也更容易;
- Resource,资源的定义是“可标识的任何东西”。除了文档文件、图像或服务(例如当天的天气预报)等能够区别于其他类型的,全都可作为资源。另外,资源不仅可以是单一的,也可以是多数的集合体;
- Identifier,表示可标识的对象。也称为标识符;
综上所述,URI 就是由某个协议方案表示的资源的定位标识符。协议方案是指访问资源所使用的协议类型名称。采用 HTTP 协议时,协议方案就是 http。URI 用字符串标识某一互联网资源,而 URL表示资源的地点(互联网上所处的位置),可见 URL是 URI 的子集。
绝对URI 格式
以 “http://user:pass@www.example.jp:80/dir/index.html?uid=1#ch1” 为例:
- "http://" ,协议方案名。使用 http: 或 https: 等协议方案名获取访问资源时要指定协议类型。不区分字母大小写,最后附一个冒号(:)。也可使用 data: 或 javascript: 这类指定数据或脚本程序的方案名;
- "user:pass" ,登录信息(认证)。指定用户名和密码作为从服务器端获取资源时必要的登录信息(身份认证),此项是可选项;
- "www.example.jp" ,服务器地址。使用绝对 URI 必须指定待访问的服务器地址。地址可以是类似 hackr.jp 这种 DNS 可解析的名称,或是 192.168.1.1 这类 IPv4 地址名,还可以是 [0:0:0:0:0:0:0:1] 这样用方括号括起来的 IPv6 地址名;
- "80",服务器端口号。指定服务器连接的网络端口号。此项也是可选项,若用户省略则自动使用默认端口号;
- "dir/index.html",带层次的文件路径。指定服务器上的文件路径来定位特指的资源。这与 UNIX 系统的文件目录结构相似;
- "uid=1",查询字符串。针对已指定的文件路径内的资源,可以使用查询字符串传入任意参数,此项可选;
- "ch1",使用片段标识符通常可标记出已获取资源中的子资源(文档内的某个位置)。但在 RFC 中并没有明确规定其使用方法,该项也为可选项。
常见的面试题
TCP三次握手
为什么要三次握手?
三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。
- 第一次握手:Client 什么都不能确认;Server 确认了对方发送正常
- 第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己接收正常,对方发送正常
- 第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常
所以三次握手就能确认双发收发功能都正常,缺一不可。、
为什么要传回 SYN?
接收端传回发送端所发送的 SYN 是为了告诉发送端,我接收到的信息确实就是你所发送的信号了。
SYN 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement[汉译:确认字符 ,在数据通信传输中,接收站发给发送站的一种传输控制字符。它表示确认发来的数据已经接受无误。 ])消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。
为什么TCP客户端最后还要发送一次确认呢?
一句话,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。
- 如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。
- 如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。
四次挥手
为什么要四次挥手?
任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。
举个例子:A 和 B 打电话,通话即将结束后,A 说“我没啥要说的了”,B回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”,A 回答“知道了”,这样通话才算结束。
为什么客户端最后还要等待2MSL?
MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。
第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
- 第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
为什么建立连接是三次握手,关闭连接确是四次挥手呢?
建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。