盛唐年间,天下安定,由于疆域太大传递信件不易,就有民间的能人异士向皇帝谏言,每个州县都建立信息司来养信鸽。由信鸽来传递信件。皇帝觉得可行遍开始施行。
一日皇帝命小吏从东都洛阳发一封信件到西京,这个小吏第一次去信息司发信件,到了信息司发现只有一个人处理信件。小吏便把信件交给了信息司的小哥,只见小哥娴熟的拿出只信鸽告诉它去西京,就放飞了,然后将信件誊抄了一份,将信件撕成了三份,并标上了序号。过了不一会小哥刚刚放走信鸽飞回来了,只见小哥又将信鸽放飞了。然后拿出三个信鸽分别将三份信件绑到信鸽的腿上,然后将信鸽放飞了。这时候小吏就问了小哥一句:”为什么刚刚只把信鸽放飞而不放信件啊!“。这时小哥不耐烦地说:”我要试试,我们州县附近有没有猎人,看看信鸽能不能飞出去。如果飞不出去就要找县衙派兵沿途检查一下路线了。“;小吏又问:”既然我们已经看到信鸽飞回来了,为什么还要再次放出去。“。小哥继续说:”西京那边还不知道他能不能发信鸽。我需要告诉他一声。“,谈话间只看到传递 1,3 号信件的鸽子飞回来了。小哥说:”又有一只鸽子飞丢了。“,小吏急忙问道:”怎么办!如果出了差错,我可是要被杀头的。“。小哥说:”莫着急我们再等一柱香的时间,如果还不回来我们在把 2 号信件重新发一次就好了。“。一炷香过后,小哥又拿出一只信鸽把 2 号信件绑到鸽子的腿上。不一会传递 2 号信件的信鸽飞回来了。只见小哥又娴熟的拿出一只信鸽放了出去,不一会飞回两只,然后小哥又放出去一只信鸽。小吏不解的问小哥:”你这个在干什么!“。小哥说:“我这是再告诉西京那边我的信息发完了。然后西京告诉我他知道了并让我把备份的信件销毁。我再告诉西京没问题”。终于皇帝的信件发完了。
小吏回去后感觉比较有意思,东都西京中间隔着两个州,信鸽是怎么如何飞的呢?他又专程去问了信息司的小哥。小哥说:”我也不知道信鸽会飞到那个州,如果信鸽飞到其他州,其他州的人会看到信鸽的目的地是西京,他会改变信鸽的飞行方向,直到信鸽飞到西京才算结束。“。
以上的小故事就是个简单 TCP 传输。
小吏便算是应用层,皇帝让他去发消息。
信息司的小哥身兼传输层和网络层。
信鸽便是链路层。
TCP/IP 分层网络
1. 应用层
应用层决定了向用户提供应用服务时通信的活动。
TCP/IP 协议族内预存了各类通用的应用服务。例如:HTTP、SSH、FTP 等。
2. 传输层
应用层的下一层就是传输层,提供处于网络连接中的两台计算机之间的数据传输
常见的传输层协议有 TCP、UDP 等。
3. 网络层
网络层又称网络互连层。
网络层用来处理在网络上流动的数据包,数据包是网络传输的最小数据单位。该层规定了通过怎样的路径到达对方的计算机,并把数据包传送给对方。
网络层的作用就是在众多选项内选择一条合适的传输路径。
4. 链路层
链路层又称数据链路层,网络接口层
用来处理连接网络的硬件部分,控制操作系统、硬件的设备驱动。
我们能够看到的交换机、网线、光纤等也属于物理层
TCP 是什么
TCP 的全称是传输控制协议(Transmission Control Protocol)位于传输层,它是一种有连接的协议,提供可靠的字节流服务[注1]。而可靠的传输服务是指,能够将数据准确可靠的传递给对方。数据为何能准确无误的送达目标处,就是因为 TCP 协议采用了三次握手策略,当然除了三次握手,TCP 协议还有其他手段来保证通信的可靠性
TCP 三次握手
①发送端首先发送一个带 SYN 标志的数据包给对方
②接收端收到标有 SYN 的数据包后回传一个带有 SYN/ACK 标志的数据包表示确认信息
③发送端在发送一个带有 ACK 标志的数据包给接收端表示握手成功
更通俗的以对象举例:
如果握手成功后连接断开,再次连接还需要重新握手
TCP 四次挥手
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
第一次挥手:
Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
第二次挥手:
Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
第三次挥手:
Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
第四次挥手:
Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
UDP 是什么
UDP 的全称是用户数据报协议(User Datagram Protocol)同样位于传输层,它是一种无连接的协议,提供面向事务的简单不可靠信息传送服
TCP 与 UDP 的差异
- TCP 是有连接的而 UDP 是无连接的
- TCP 是可靠的连接而 UDP 是不可靠的
- UDP 不需要各种可靠性策略所以相比 TCP 性能要高不少
- 因为 UDP 的连接步骤少,报头内容少所以相比 TCP 更加的省流量
- TCP 只能一对一连接传递消息而 UDP 可以一对一、一对多、多对一和多对多
抓包软件 Wireshark
注1:字节流服务是指,为了方便传输,将大块数据分割成报文段为单位的数据包进行管理的服务
【TCP相关疑问】
最后整理几个常见的TCP相关的疑问:
- Q1 为什么在TCP协议里,建立连接是三次握手,而关闭连接却是四次握手呢?
- A1 因为当处于LISTEN 状态的服务器端SOCKET当收到SYN报文(客户端希望新建一个TCP连接)后,它可以把ACK(应答作用)和SYN(同步作用)放在同一个报文里来发送给客户端。但在关闭TCP连接时,当收到对方的FIN报文时,对方仅仅表示对方没有数据发送给你了,但未必你的所有数据都已经全部发送给了对方,所以你大可不必马上关闭SOCKET(发送一个FIN报文),等你发送完剩余的数据给对方之后,再发送FIN报文给对方来表示你同意现在关闭连接了,所以通常情况下,这里的ACK报文和FIN报文都是分开发送的。
- Q2为什么TIME_WAIT 状态还需要等2*MSL秒之后才能返回到CLOSED 状态呢?
- A2因为虽然双方都同意关闭连接了,而且握手的4个报文也都发送完毕,按理可以直接回到CLOSED 状态(就好比从SYN_SENT 状态到ESTABLISH 状态那样),但是我们必须假想网络是不可靠的,你无法保证你最后发送的ACK报文一定会被对方收到,就是说对方处于LAST_ACK 状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT 状态的作用就是用来重发可能丢失的ACK报文。
- Q3关闭TCP连接一定需要4次挥手吗?
- A3不一定,4次挥手关闭TCP连接是最安全的做法。但在有些时候,我们不喜欢TIME_WAIT 状态(如当MSL数值设置过大导致服务器端有太多TIME_WAIT状态的TCP连接,减少这些条目数可以更快地关闭连接,为新连接释放更多资源),这时我们可以通过设置SOCKET变量的SO_LINGER标志来避免SOCKET在close()之后进入TIME_WAIT状态,这时将通过发送RST强制终止TCP连接(取代正常的TCP四次握手的终止方式)。但这并不是一个很好的主意,TIME_WAIT 对于我们来说往往是有利的。