初探TCP/IP四层模型

Hokori 3月31日

TCP/IP

TCP/IP协议族是一个四层协议系统,自底而上分别是数据链路层、网络层、传输层和应用层。每一层完成不同的功能,且通过若干协议来实现,上层协议使用下层协议提供的服务。

TCP/IP

我们自低向上来简单了解一下TCP/IP协议族是怎么工作的


数据链路层

数据链路层实现了网卡接口的网络驱动程序,以处理数据在物理媒介(比如以太网、令牌环等)上的传输。

数据链路层两个常用的协议:

  • ARP协议(Address Resolve Protocol,地址解析协议)
  • RARP协议(ReverseAddress Resolve Protocol,逆地址解析协议)

ARP协议

一个根据IP地址获取物理地址的一个TCP/IP协议

主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。

地址解析协议是建立在网络中各个主机互相信任的基础上的,网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其记入本机ARP缓存;由此有心者就可以向某一主机发送伪ARP应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个ARP欺骗。

RARP协议

一个根据物理地址获取IP地址的一个TCP/IP协议

仅用于网络上的某些无盘工作站。因为缺乏存储设备,无盘工作站无法记住自己的IP地址,但它们可以利用网卡上的物理地址来向网络管理者(服务器或网络管理软件)查询自身的IP地址。运行RARP服务的网络管理者通常存有该网络上所有机器的物理地址到IP地址的映射。


网络层

网络层实现数据包的选路和转发。

网络层的协议有:

  • IP协议(Internet Protocol,因特网协议)
  • ICMP协议(Internet Control Message Protocol,因特网控制报文协议)

IP协议

IP协议主要用于在主机之间的寻址和选择数据包路由,提供的是不可靠、无连接的数据包传输服务。

  • 不可靠,就是在数据的传递过程中,不需要检测网络是否连通,不能保证IP数据报能成功的到达目的地。
  • 无连接,表示IP协议并不维护任何关于后续数据报的状态信息,每个数据报的处理是相互独立的。普通的IP首部长为20个字节,除非含有选项字段。

IP协议根据数据包的目的IP地址来决定如何投递它。如果数据包不能直接发送给目标主机,那么IP协议就为它寻找一个合适的下一跳(next hop)路由器,并将数据包交付给该路由器来转发。多次重复这一过程,数据包最终到达目标主机,或者由于发送失败而被丢弃。可见,IP协议使用逐跳(hop by hop)的方式确定通信路径。

当IP协议找到可以为它转发数据包的路由时把数据包交给路由器后就不管事了,这个数据包将由这个路由器去传送到目的地,所以IP协议不知道到达目的地的完整路径(除了可以直接发送到目标主机的以外)

IP协议

ICMP协议

ICMP协议是IP协议的重要补充,其实现基于IP协议,必须由每个IP模块实现。主要用于检测网络连接。当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。

在IP协议发送数据包时,经常有数据包被路由器 (处理不了) 丢弃或者目的端口号错误的情况,<br/>
这时返回这个错误信息的工作就是ICMP协议发送的报文完成的。

ICMP协议

除此之外,ICMP协议还有改变路由、源点抑制、实现ping等命令的功能

  • 改变路由:计算机根据自己的路由信息(路由表)来决定传送目标。不知道发给谁好的时候,就将数据包发给设为默认网关的路由器。被指定为默认网关的路由器接收到数据包,发现将数据包发给局域网内的其它路由器会比较快的时候,将这一信息通过ICMP 通知发送方。计算机收到这个报文后,重写自己的路由表,与对方的通信将在一段时间里经由被指定的路由器来实行。
  • 数据包集中到达某一路由器后,数据包因为来不及被处理,有可能被丢弃的情况。这时候,向送信方发送的是ICMP 源点抑制报文,用来使送行方减慢发送速度。
  • ping命令:使用了两个ICMP报文(此处以Windows系统为例,有些操作系统发送的是UDP数据包,返回一个ICMP错误报文)

    • 向目标服务器发送回送请求报文,这个请求报文除了类型和代码字段,还被追加了标识符和序号字段。标识符和序号字段分别是16 位的字段。ping 命令在发送回送请求报文时,在这两个字段里填入任意的值。对于标识符,应用程序执行期间送出的所有报文里填入相同的值。对于序号,每送出一个报文数值就增加1。而且,回送请求的选项数据部分用来装任意数据。这个任意数据用来调整ping 的交流数据包的大小。
    • 如果目标服务器允许回答ping命令,会发送回送请求报文,返回的这个报文与发送的报文基本无异,只是源和目标的IP地址字段被交换了,送信方的计算机可以通过收到回送回答报文,来确认目标服务器在工作着。进一步,记住发送回送请求报文的时间,与接收到回送回答报文的时间一比较,就能计算出报文一去一回往复所需要的时间(同4)。但是,收到的回送回答报文里写的只是类型和代码的话,发送方计算机将无法判断它是否是自己发出去请求的回答。因此,前面说到的标识符和序号字段就有它的意义了。将这两个值与回送回答报文中的相同字段值一比较,送行方计算机就能够简单地检测回送回答是否正确了。执行ping 命令而调查的结果没什么问题的话,就将目标服务器的IP 地址,数据大小,往复花费的时间打印到屏幕上。


传输层

传输层为两台主机上的应用程序提供端到端(end to end)的通信。与网络层使用的逐跳通信方式不同,传输层只关心通信的起始端和目的端,而不在乎数据包的中转过程。

传输层的协议有:

  • TCP协议(Transmission Control Protocol,传输控制协议)
  • UDP协议(User Datagram Protocol,用户数据报协议)

TCP协议

TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端,为应用层提供可靠的、面向连接的字节流服务。

所谓的字节流服务(Byte Stream Service)是指,为了方便传输,将大块数据分割成以报文段(segment)为单位的数据包进行管理。而可靠的传输服务是指,能够把数据准确可靠地传给对方。

一言以蔽之, TCP 协议为了更容易传送大数据才把数据分割,而且 TCP 协议能够确认数据最终是否送达到对方。

面向连接、三次握手

  • 是指在数据通信开始之前先做好通信两端之间的准备工作。

为了准确无误地将数据送达目标处,TCP 协议采用了三次握手 (three-way handshaking)策略。用 TCP 协议把数据包送出去后,TCP 不会对传送后的情况置之不理,它一定会向对方确认是否成功送达。

  • 第一次握手:

    • 客户端向服务端发送连接请求报文段。该报文段的头部中SYN=1ACK=0,同时选择一个初始序号seq=x。请求发送后,客户端便进入SYN-SENT状态。
  • 第二次握手:

    • 服务端收到连接请求报文段后,如果同意连接,会发送一个应答:SYN=1,ACK=1,seq=y,ack=x+1。发送完应答后服务端进入SYN-RCVD状态。
  • 第三次握手:

    • 客户端收到服务端连接同意的应答后,还会向服务端发送一个确认报文段,表示:服务端发来的连接同意应答已经成功收到。该报文段的头部为:ACK=1,seq=x+1,ack=y+1。该报文发送完毕后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手

三次握手

为什么不是两次握手:是为了防止已失效的连接请求报文段突然又传送到了服务端,造成服务端资源的浪费。

  • 在一次TCP连接中,客户端A向服务端B发送连接请求SYN报文段,假如这个报文段没有及时被服务端B接收,而是滞留在网络的某处,于是客户端A超时重传,再次发送请求连接并且顺利与服务端B建立了连接,交换数据后断开连接。滞留在网络中的某处的陈旧报文就变成了失效的连接请求报文。
  • 但如果这个失效的请求SYN报文段,现在又突然传送到了服务端B处,设想这时是使用两次握手而不是三次握手,服务端B就以为客户端A现在建立请求连接,于是服务端B发出确认,新的连接就建立了,服务端B分配资源,等待客户端A传送数据,但客户端A并没有想要建立TCP连接,不会理会服务端B发送的应答,也不会向服务端B传送数据,于是服务端B就白白等待,空耗资源。
  • 使用三次握手可以避免这个情况。服务端B收到客户端A的失效的陈旧SYN报文段,向客户端A发送SYN报文段,选择自己的序号seq=y,确认收到客户端A的SYN报文段,确认号ack=x+1。第三次握手客户端A收到B的SYN报文段后,从确认号就可得知不应理睬这个SYN报文段(因为A现在并没有发送seq=x的报文段)。这时,客户端A会发送复位报文段,这个复位报文段中,RST=1,ACK=1,确认号ack=y+1。服务端B收到A的复位报文,就知道不建立TCP连接,不会分配资源等待A发送数据。

为什么不是四次握手:因为三次握手已经能说明握手时的通信是正常的,四次握手、五次握手就显得浪费了。

UDP协议

它是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。

UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。

应用场景

因为UDP不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失几个数据包,也不会对接收结果产生太大影响。

应用层

应用层负责处理应用程序的逻辑。

常见协议:HTTP、DNS等

ping是应用程序,而不是协议,前面说过它利用ICMP报文检测网络连接,是调试网络环境的必备工具。

HTTP协议

HTTP是运行于TCP协议之上,基于C/S架构进行通信的无状态协议

所谓无状态:即指它不对之前发生过的请求和响应的状态进行管理。也就是说,无法根据之前的状态进行本次的请求处理。

尽管如此,无状态协议也有它的优点。由于不必保存状态,自然可减少服务器的 CPU 及内存资源的消耗。从另一侧面来说,也正是因为 HTTP 协议本身是非常简单的,所以才会被应用在各种场景里。

HTTP有多个版本,如HTTP1.0、HTTP1.1、HTTP2.0、HTTP/3(基于UDP协议)

我们使用的浏览器在访问网页时正是使用的HTTP协议。


HTTP报文

用于HTTP协议交互的信息被称为HTTP报文。

请求端(客户端)的HTTP报文叫做请求报文,响应端(服务器端)的叫做响应报文

HTTP报文本身是由多行(用CR+LF作换行符)数据构成的字符串文本HTP报文大致可分为报文首部和报文主体两块。两者由最初出现的空行(CR+IF)来划分。通常,并不一定要有报文主体。

图:请求报文(上)和响应报文(下)的结构


图:请求报文(上)和响应报文(下)的实例


HTTP状态码

HTTP状态码负责表示客户端HTTP请求的返回结果、标记服务器端的处理是否正常、通知出现的错误等工作。

DNS协议

用于解析域名、将域名转换为IP的协议

浏览器DNS解析过程:

  • 检查浏览器DNS缓存
  • 若未命中域名,检查操作系统DNS缓存
  • 若仍未命中域名,检查本地路由器DNS缓存
  • 若仍未命中域名,本机(一般会)向本地域名服务器发起递归查询
  • 若仍未命中域名,本地域名服务器向根域名服务器发起迭代查询

[递归查询]:如果主机所询问的本地域名服务器不知道被查询的域名的IP地址,那么本地域名服务器就以DNS客户的身份,向其它根域名服务器继续发出查询请求报文(即替主机继续查询),而不是让主机自己进行下一步查询。

[迭代查询]:当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的IP地址,要么告诉本地服务器:“你下一步应当向哪一个域名服务器进行查询”。然后让本地服务器进行后续的查询。




参考资料:
理解TCP
TCP/IP四层模型
图解HTTP
DNS解析过程

icon_biggrin.pngicon_neutral.pngicon_twisted.pngicon_arrow.pngicon_eek.pngicon_smile.pngicon_sad.pngicon_cool.pngicon_evil.pngicon_mrgreen.pngicon_exclaim.pngicon_surprised.pngicon_razz.pngicon_rolleyes.pngicon_wink.pngicon_cry.pngicon_confused.pngicon_lol.pngicon_mad.pngicon_question.pngicon_idea.pngicon_redface.png
expand_less