最近又重温了TCP/IP的知识,果然比第一次看的时候有感悟多了,那就写一点东西来总结一下。
现在我们主要了解计算机网络的两种模型:OSI模型和TCP/IP模型。需要注意的是由于OSI模型过于复杂导致难以实现,因此导致TCP/IP模型更早地应用在现实中。这也使得TCP/IP模型成为事实上的标准,而OSI仅仅是纸面上的标准。
在OSI模型中,将计算机网络分成了7层,而在TCP/IP模型中则分成了4层,其各层对应关系如下表所示:
OSI | TCP/IP | 对应网络协议 | 所在位置 |
应用层 | 应用层 | TFTP, FTP, NFS, WAIS | 主机 |
表示层 | Telnet, Rlogin, SNMP, Gopher | ||
会话层 | SMTP, DNS | ||
传输层 | 传输层 | TCP, UDP | |
网络层 | 网际层 | IP, ICMP, ARP, RARP, AKP, UUCP | 媒介 |
数据链路层 | 网络接口层 | FDDI, Ethernet, Arpanet, PDN, SLIP, PPP | |
物理层 | IEEE 802.1A, IEEE 802.2到IEEE 802.11 |
在整个计算机网络体系中,最核心的当属是位于传输层的TCP与UDP协议了。因为他们位于主机协议栈的最底层,向上方应用层提供不同的数据交付方式。
因为UDP协议相对TCP协议来说相对简单,就先回顾一下UDP协议。
UDP的全称也叫做用户数据报协议(User Datagram Protocal),它有以下几个值得注意的特点:
如下是UDP报文头部格式
其中从1到8字节分别是来源端口号、目的端口号、报文长度、检验和,每个字段各占两字节。
UDP的通信方式较为简单,发送端发送完一个报文继续发送下一个,待将所有报文发送完毕通信就结束了。
接收方也是如此。
传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP协议所要实现的功能是端到端之间的可靠传输,因此,相较于UDP协议而言,TCP协议要复杂的多。
相对于UDP协议,TCP协议有下面的几个特点:
此外,还需要注意的是,TCP提供的是全双工的通信。
要理解TCP协议中各功能的实现,要先从TCP的数据封包结构开始。
下面的图片就是TCP数据封包的结构示意图:
各个字段功能如下:
总之要记住,确认号=N,表示N-1及其之前的封包都已经收到。
选项字段(最多40字节):每个选项的开始是1字节的kind字段,说明选项的类型。
其中上面的3、4、7、8是重点。
为了搞明白下面要说的TCP的一些机制,首先需要知道TCP协议能够实现可靠传输的一个基本的原理–超时重传。
说来很简单,其实就是收到当接收方收到一个数据封包的时候就向发送方发送一个确认数据封包。而当发送方发送完一个数据封包经过一段时间没有收到接收方的确认封包时,就会将上一个封包再次向接收方发送一次。
当然,TCP中真正的机制比这个要复杂的多,但是基于的原理都是一样的。
在说TCP连接之前先插播一个小故事。
说是有一天,一个程序员到酒吧去喝酒,于是跟服务员之间发生了如下的对话。
程序员:我要一瓶酒。
服务员:你确定你要一瓶酒?
程序员:我确定我要一瓶酒。
于是服务员就给了程序员一瓶酒。
是不是很罗嗦?没错,这就是典型的TCP连接建立的过程。如下面的图:
图中的小人就是客户端,另一边不用说也知道就是服务器端。图中画的比较简略,大概过程是下面这样:
下面过程中,ACK表示上面说的TCP包头中的确认标识,ack表示确认号(4字节那个)。
以上步骤就是俗称的“TCP三次握手”。
当然,最初的时候服务器肯定是处于监听状态啦,要不然怎么能够对客户端的数据封包做出回应呢。
要注意的是,这里有个很经典的问题就是为什么在收到服务器的确认封包后还要再向服务器发送一个确认封包呢?
这主要是因为TCP协议的下层网络是不可靠的,也就是说数据封包可能丢失也可能滞留在某个节点很长时间。
所以这就有一种可能就是客户端发送给服务器的封包在网络中滞留了,这样客户端当然也就不会收到服务器发来的确认封包。还记得TCP有个超时重传机制吗?没错,这个时候客户端是以为自己发出去的封包在网络中是丢了的,于是过一段时间又会重传刚才的封包。
幸运的是,这次重传的封包十分顺利的到达了服务器,于是服务器也十分顺利的向客户端发出了确认封包。本来就要愉快的建立连接了,可是天有不测风云,刚才滞留的请求封包此时到达了服务器这里。
这个时候服务器就懵了,这到底是客户端又要跟我建立一次连接还是刚才滞留的封包又给了我呢?
于是这个时候就需要客户端再发送一个确认封包给服务器了。
当然,有连接建立,就有连接释放,客户端与服务器之间的连接释放过程大概是下面这个样子的。
跟建立连接的时候差不多,大概过程大概向下面这样:
如上步骤就是俗称的“TCP4次挥手”。
这里之所以是4次,主要是与建立连接时相比,服务器的确认和结束被分成了两个封包分别发送了出去。
当然,这里也有个比较经典的问题就是客户端为什么在发送完最后一个封包后还要再等待一段时间?
这里也主要是因为TCP协议下层的网络并不是很可靠,有可能客户端发出的最后一个封包在路上丢了而导致服务器等待很长世间浪费服务器资源。于是就让客户端再等待一段时间,这样当服务器收不到客户端发来的确认封包时,还会再重传一个连接结束封包,此时的客户端再次受到这个连接结束封包后还可以再重传一次确认封包来让服务器正常结束连接。这样,就不会白白浪费服务器资源了。
最后,再从整个网络的范围来看,一个数据封包到底是要经过怎样的旅程才会从出发地到达目的地呢?
以TCP协议为例,当TCP协议接到上层应用层交付下来的数据封包后,就在这个数据封包的前面加上TCP的头部。
然后,再交付给下层的网络层。
网络层接收到上层传输层传递下来的封包后,就在封包的头部加上IP协议的头部和网际接口层的首部和头部后经过层层路由,最终到达距离目的主机最近的路由器。
然后距离目的主机最近的路由器再对数据包进行解包,去掉网际接口层和网络层的封装后将数据包送到目的主机的传输层(TCP接收缓冲池),再由目的主机的传输层交给上层的应用层。
一图以蔽之:
维基百科-TCP/IP协议簇
维基百科-用户数据报协议
维基百科-传输控制协议