(从“网络中的基本概念”博客中可知:TCP协议的特点是有连接(先建立连接再通信),可靠传输(TCP最核心的特点,数据有没有发送到接收方,发出方可知晓),面向字节流(与文件中字节流相同),全双工(双向通信,A可以和B通信,B可以和A通信,能同时进行;相反半双工就是两个通信不能同时进行)。)
1.确认应答
确认应答就是对数据进行编号,来确定该应答报文是在应答哪一个数据,解决了网络传输中后发先至的情况。
一个TCP报文中有一个32位序号(给发送的每个数据编号),和一个32位确认序号(如果当前报文是一个普通报文,则确认序号无效,如果当前报文是一个应答报文,确认序号就表示应答的是哪一个报文)。
编号方式:由于TCP是面向字节流的,在编号的时候也按照字节的方式编写。如若发送一个长度位1000字节的数据,TCP报头的序号是1,整个报文长度是1000,相当于把1到1000的字节全部发送了,应答报文是一个报头没有负载,则应答报文的序号就是1001。
2.超时重传
确认应答解决了接收到应答报文后,判断应答的是哪个报文的情况,但是如果没有接收到应答报文的时候,就需要引用超时重传来处理了。
在没有收到应答报文时,主机A不会立马放弃,会在一定时间内触发超时重传。
遇到丢包问题,首先丢包是无差别丢包,具有随机性,可能丢失普通报文,有可能丢失ACK。
(1)普通报文丢失
发送方等待一定时间后,没有收到应答报文,就会重传数据。
(2)ACK丢失
主机A发送数据,数据到达主机B,但是发送没有收到ACK,发送等待一定时间后,就会重传数据,此时主机B收到相同的两份数据,此时如果read读出两份数据相同就会数据去重,自动丢弃,保证应用层读到的数据不重复。
超时重传的时间间隔会逐次增大,如果几次重传之后仍然不能收到返回的ACK,不会再无休止的重传,就只能断开连接,后尝试重新连接,如果重连也连接不上,就只能彻底放弃。
3.连接管理
连接管理即建立连接“三次握手”和断开连接“四次挥手”。
具体内容参考上篇博客http://t.csdn.cn/TcDuX
4.滑动窗口
在保证可靠性的前提下,就要考虑TCP的效率问题,本质上将等待ACK的时间重叠在一起,减少等待时间,滑动窗口是提高可靠性的机制。
在发送数据时,每次传输都需要等待ACK,收到ACK之后再发送新的数据,在滑动窗口的情况下,可以在被等待的前提下最多可以发送N条数据,此时的N就是滑动窗口的大小,N越大即同时发送的数据越多,传输的效率就越高,但是N的值也不是越大越好,传输效率是受发送效率和接收效率影响。
5.流量控制
流量控制本质上是对滑动窗口的制约,滑动窗口是窗口越大,发送效率越高,流量控制则是针对滑动窗口进行制约,如果发送效率>接收效率,再增加滑动窗口大小来提高发送效率,也不能提高整体的效率,反而会因为接收方丢包,触发更多超时重传,降低效率。但是要如何确定发送效率是否和接收效率一致呢?
主机A向主机B发送数据时,数据先被放入缓冲区中,主机B可通过调用read()方法从缓冲区中读取数据。流量控制就是通过接受缓冲区剩余空间的大小作为下一次发送时滑动窗口的大小。
6.拥塞控制
滑动窗口通过改变窗口大小控制发送速率,流量控制通过缓冲区剩余空间的大小站在接收方的角度改变滑动窗口的大小来控制发送效率,但是TCP整体传输不仅仅有发送方和接收方,中间还有一系列转发设备。
流量控制和拥塞控制都是通过影响滑动窗口的大小来制约发送方的发送速率,最终滑动窗口的大小就是流量控制的窗口和拥塞控制的窗口的较小值。因为如果拥塞控制的窗口大,流量控制的窗口小,中间节点的转发能力强,接收端的代码处理的慢;如果拥塞控制的窗口小,流量控制的窗口大,中间节点的转发能力弱,接收端的代码处理的快。
拥塞控制是通过实验的方法来寻找合适的窗口大小:(1)刚开始按照小的窗口大小发送;(2)如果不丢包,就逐渐放大发送窗口的大小;(3)放大到一定值时速率太快,造成丢包,形成拥塞,触发超时重传,造成进一步丢包,发送方减小窗口大小。
当经过以上多次循环后,可达到一个动态平衡,发送效率不慢,接近能承受的极限,同时尽量减少丢包,能够适应网络环境。
7.延时应答
延时应答是控制流量控制下的窗口大小不要太小。延时一段时间后,应用程序在不停的消耗接收缓冲区,使得再流量控制下返回的缓冲区剩余空间大小就能保存在一个合理的状态下。
8.捎带应答
基于延时应答的策略。正常情况下,客户端向服务器发送请求时,服务器收到请求后操作系统内核立即返回ACK,而响应数据是由应用程序代码发送的,二者存在明显的时间差并不能合并,但是延时应答之后,时间上就能够重合,操作系统内核返回的ACK和服务器应用程序代码发送的响应数据就能够合成一个报同时发送!
9.面向字节流
面向字节流是指在读写载荷数据时,按照字节流的方式进行读取。客户端向服务器发送数据时,这些数据都进入缓冲区当中,接收方就区分不了这些数据是哪几个应用层数据报发送的,也不知道这些数据分别要去哪,这就引起了“粘包问题”。
如果一个TCP连接,里面只传一个应用层数据报,不会引起“粘包问题”,但是如果一个TCP连接,里面传输多个应用层数据报,就容易出现上述情况,引起“粘包问题”。“粘包问题”的解决方法:在应用程序代码中,明确包的边界,(1)使用分隔符,(2)约定长度。
10.异常处理
1.主机关机(按照固定程序关机)
按照固定程序关机,会先杀死所有的用户进程,释放进程PCB,释放文件描述符上对应的文件资源,调用stack.close(),触发“四次挥手”,如果“四次挥手”完毕,再继续关机;如果“四次挥手”还没有完成就已经关机,客户端多次传输FIN无响应后自动放弃。
2.程序崩溃
与主机关机相同,但是如果程序崩溃,进程断开,内核会继续完成“四次挥手”过程。
3.主机掉电
(1)接收方掉电
客户端发送数据,不能收到接收方返回的ACK,多次发送后断开连接,如果重新不能建立连接,就会认为当前网络出现问题,放弃发送数据。
(2)发送方掉电
接收方一直在等待接受数据,一直没有数据发送过来,接收方不能区分是发送方没有发送方数据还是发送方出现问题,因此接收方有一个机制,如果一段时间没有收到数据,就会在一定周期内给发送方发送一个特殊的报文(ping),发送方会给接收方回复一个特殊的报文(pong),以此来判定发送方是否出现问题。
4.网线断开
与主机掉电相同。