写这篇文章我已经考虑了很久,总是不愿意草草的下笔,总想等到自己对TCP理解的更深入些再提笔来写。但是又觉得,在写这篇文章的过程中,才能发现自己哪些地方理解的还不够深入,哪些地方已经掌握了。因为检测自己是否理解了一个技术原理的很好的途径,就是看自己能不能把它讲出来。下面就看看我能讲到什么程度吧。
TCP是什么?
TCP是Transmission Control Protocol(传输控制协议)的缩写。它位于网络OSI七层模型中的传输层(IP协议位于网络层;ARP协议位于数据链路层,ARP协议将IP地址解析为物理地址)。程序中的数据会先由TCP协议包装,然后再由IP协议包装,各层由上到下用自己的协议对上层传下来的数据进行包装,传到对端后,各层再由下到上解析自己的协议并把本层解析后的数据交给更高层的协议处理。
TCP的特点
- TCP是面向连接的,这里的连接指的是逻辑上的连接(虚连接),就是说在通讯的双方都维护一个“连接状态”,看上去就像有链接一样,而实际上数据在网络中的传输是没有链接的。
- 每一个TCP链接有且只有两个端点,数据的点对点传输。
- TCP是可靠的,使用TCP连接传送的数据,无差错,不重复,不丢失。
- TCP是全双工的,TCP允许通信双方的应用进程在任何时候向对方发送数据。
- TCP是面向字节流的,即二进制流,TCP只管数据传送,而不管是什么数据,或者数据是什么结构。
- TCP的发送方和接收方都设有发送缓存和接收缓存,发送方应用程序把数据放入发送缓存,TCP在合适的时候将数据发送出去,放入接收方的接收缓存。接收方应用程序在合适的时候从接收缓存中取出数据。这就好比生活中的邮箱,我们需要寄信的时候就把信放到邮箱里,邮递员会在合适的时候把我们的信件取走寄出,放入对方的邮箱中,收信人也会在需要的时候去查看他的邮箱。我觉得这便是一种解耦,应用程序不需要知道通信的细节,它只需要把数据传给专门负责通信的TCP协议,真正的数据通信则由TCP代劳。
TCP可靠传输的工作原理
我们知道,TCP下面的网络层提供的是不可靠的传输。而TCP要保证可靠传输,就要采取适当的措施:
- 当传输的数据出现差错时,让发送方重传出现差错的数据。
- 在接收方来不及处理收到的数据的时候,让发送方适当降低发送数据的速度。
那么,发送方是如何知道传输的数据出现了差错呢,在正常的情况下,即传输的数据没有出现差错的时候,接收方会向发送方回应一个确认号。当发送方经过了一段时间之后仍然没有收到接收方的确认,就认为刚才发送的数据丢失了,因此就对刚才发送的数据进行重传,这便是超时重传。这就像两个人对话,A对B说一句话,B要回应A说他听见了第一句,然后A再对B说下一句,B再回应A说听见了第二句……如果A经过了一段时间没有收到B的回应,那么A就会认为B没有听见,A就会再说一次。这其实就是一种规则,而这种规则就是所谓的协议,通信双方都要遵守这个协议,可靠通信才能达成。
TCP报文首部格式
如图所示:
- Sequence Number即报文段序号,TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号,起始序号要在连接建立时设置。该序号指本报文段所发送的数据的第一个字节的序号。
- Acknowledgment Number即确认号,表示期望收到对方下一个报文段数据的第一个字节的序号。
通过序号和确认号,解决了网络传输中报文段乱序和报文段丢失的问题。
TCP Flags:
- Ack的值来控制确认号是否有效,只有当ACK=1时,确认号才有效。
- Urgent=1表示该报文段紧急,发送方会将紧急数据插入该报文段数据的最前面。
- Push=1时,接收方会尽快的解析并交付给上层,而不再等到缓冲区填满。
- Reste=1时,表明TCP连接中出现严重差错,必须释放连接,然后重新建立连接。
- Syn用来在连接建立时同步序号。Syn=1表示该报文为一个连接请求或连接接受报文。
- Fin用来释放一个连接,Fin=1时表明发送方的数据已发送完毕,并请求关闭连接。
TCP滑动窗口(Window):滑动窗口用来做网络流控制,因为TCP要做到可靠传输,需要知道网络实际的数据处理速度,然后根据网络的实际情况进行数据发送,这样才不会引起网络拥塞,导致丢包。Window这个字段被接收端用来告诉发送端自己还有多少缓冲区可以用来接收数据。于是发送端就可以参考这个值来发送数据,避免接收端处理不过来。
TCP连接的建立与释放
TCP连接的建立,三次握手
- 起初Client端和Server端都处于Close状态。
- 服务器端创建TCB(传输控制块),进入Listen(监听)状态。
- 客户端首先建立TCB,然后向服务器发送连接请求报文段。客户端进入同步已发送状态。
- 服务器收到连接请求后,向客户端发送确认。服务器进入同步收到状态。
- 客户端收到服务器的确认后,客户端进入连接建立状态。同时向服务器发送确认的确认。
- 服务器收到客户端发送的确认的确认后,进入连接建立状态。
TCP连接的释放,四次挥手
- 连接释放前双方都处于连接建立状态。
- 客户端向其TCP发送缓冲放入连接释放报文段(Fin=1),停止再发送数据,客户端进入终止等待_1状态,等待服务器的确认。
- 服务器收到释放连接请求后发出确认,服务器进入关闭等待状态。此时TCP连接处于半关闭状态,即客户端已经没有数据要发送了,但是服务器要发送数据,客户端仍要接收。
- 客户端收到服务器的确认后,进入终止等待_2状态。
- 服务器也没有要发送的数据了,则向客户端发送Fin=1的连接释放请求,服务器进入最后确认状态。
- 客户端收到服务器的连接释放请求后,进入时间等待状态,并向服务器发送确认。
- 服务器收到客户端的确认后,进入Close状态。
- 客户端经过时间等待计时器设置的时间后,进入Close状态。
所谓的四次挥手,实际上是两个两次握手,因为TCP是全双工通信,双方都需要告诉对方我要关闭了,并得到对方的确认。
总结
此文梳理了一下TCP协议的基本原理,也仅仅是最基本的东西而已,由于TCP协议过于复杂,有一些算法自己也没有完全理解,写下这篇文章,算是对自己近期所学的一个反馈吧。