TCP协议特点:面向连接、字节流、可靠传输
1.使用TCP协议的双方必须先建立连接,并且双方都必须分配相应的内核资源。TCP的连接是全双工的,也就是说双方可以根据一个连接进行读写操作。
1.当发送方应用多次进行写操作的时候,TCP发送模块会先把数据放在发送缓冲区中,当TCP发送模块真正发送的时候,这些在发送缓冲区中的数据才可能被封装成一个或多个报文段发出。所有根据以上结论,应用程序执行的写操作的次数和TCP发送的报文段个数没有对应的数量关系。
2.当接收端收到一个或多个报文段数据后,TCP模块必须把它们携带的应用层数据必须按照报文段序号把它们放到TCP接受缓冲区中。同时通知应用程序读取数据,这样应用程序就可以一次读出数据或多次读出数据,这取决于应用程序读缓冲区的大小。根据以上结论得出,TCP读取操作的次数跟接收报文段个数也没有固定的关系
总结:发送端执行的写操作次数与接受端的读操作次数没有任何数量关系,应用程序的发送和接收是没有边界限制的,UDP就不是这样,在这里不详细说了
如图TCP字节流服务过程:
以上就是字节流服务过程:
从图中我们就可以看见,发送短调用的发送次数,和接收短的接受次数并不一样。所有的数据都是先进入缓冲区,在进行操作。封装成报文段进行发送或接收。
TCP协议是可靠的传输协议,支持这种可靠传输的机制有:
1.kind:说明选项类型。
2.length:表示该选项的总长度。
3.info:选项的具体信息。
kind类型如图所示:
1、首先服务器通过LISTEN系统调用,进入LISTEN状态,表示被动打开,被动等待客户端的连接,服务器监听到某个客户端的连接请求后,这个连接请求被称为同步报文段。之后TCP会将其放到内核等待队列中,并向客户端发送带SYN的确认报文段,之后该连接就会处于SYN_RCVD状态。那么这个时候如果服务器收到了客户端的ACK确认报文段,服务器进入ESTABLISHED,这个状态可以让双方进行数据传输。
1、当客户端主动关闭连接时,客户端主动调用CLOSE,服务器接收到客户端的关闭报文段后,服务器返回ACK确认报文段,是连接进入CLOSE_WAIT状态。这个状态的就是跟字面意思一样,等待服务器关闭连接。这个时候服务器也会给客户端发送一个结束报文段,这个时候进入LAST_ACK。接下来就是等待客户端结束连接的最后一次确认。
1、首先客户端通过CONNECT系统调用,给服务器发送同步报文段。使系统进入YSN_SENT状态。接下来会有两种可能,如果连接失败,该连接将会恢复到CLOSED状态,如果该客户多收到服务器返回的同步报文段,确认报文段,说明该客户端成功连接服务器。连接转移到ESTABLISHED状态(功能通上)
1、当客户端关闭时,客户端发送一个关闭连接报文段,同时连接进入SFIN_WAIT_1状态,如果接收到服务端ACK确认,连接状态进入FIN_WAIT_2状态。当服务端也发送了结束报文段,那么客户端也会发送ACK确认,客户端进入TIME_WAIT状态。
参照图片详细了解连接转移过程
首先我们来回顾下我们以前了解过的,TCP头部结构有6个标识位
以上就是我们讲到以下内容的时候需要用到的知识点
开始介绍一下三次握手的过程:
三次握手建立后,客户端与服务器开始传送数据。
三次握手示意图:
接下来,我们来介绍下四次握手关闭
接受连接缺需要4次握手,LISTEN状态下建立连接后,它可以把同步报文段和确认报文段合并成一个报文段来进行发送,确认报文段起到应达作用,同步报文段起到同步作用,也就是三次握手中的第二个报文段其实是发挥了两个作用
在关闭连接时,当收到对方的结束报文段时,表示对方没有数据发给你了,但是自己的数据未必全部发送完毕,所以你可能还需要继续发送一些数据之后在发送结束报文段给对方了表示你同意现在可以断开连接,所以关闭连接需要四次握手
如果把三次握手改成两次握手,就有可能发生死锁。关于死锁,(搜索一下)
四次握手示意图:
在TCP详解(二)中,提到过,当客户端收到服务器的结束报文段后,不会立即进入CLOSED状态,而是转移到TIME_WAIT状态下,在这个状态下,客户端要等待一段2倍的MSL(报文段最大生存时间)时间。等待这个时间后才能完全关闭。TIME_WAIT状态的持续时间是MSL的2倍,这就足以让某个方向上的分组最多存活msl秒即被丢弃,另一个方向上的应答最多存活msl秒也被丢弃。 通过实施这个规则,我们就能保证每成功建立一个TCP连接时。来自该链接先前化身的重复分组都已经在网络中消逝了。
可靠的终止TCP连接:
例如在四次握手时,如果第三个报文段丢失,这个时候服务器将重新发送这个报文段,所以客户端需要停留在摸个状态来处理重复信息。否则客户端将会向服务器发送复位报文段,让服务器误认为这是一个错误
保证延迟来的TCP报文段有足够的时间去识别并丢弃:
在Linux系统上,一个TCP端口不能被同时打开多次,当一个TCP连接处于TIME_WAIT状态时,我们将无法立即使用该连接占用的端口建立一个新连接。
但是我们反过来考虑,如果不存在这种机制,那么服务器刚关闭连接,又建立了一个类似的连接,成为“原链接化身”,这个“化身“就有可能就收到属于原来连接的数据报文段,这种情况是不允许出现的。
修改内核参数
尽可能被动关闭连接
将长连接修改为短连接
通过套接字选项尽可能回避IME_WAIT状态带来的负面影响
曾经在TCP协议详解(一)中介绍了TCP的头部信息,头部中有6位的标识字段,这6位中有一位时RST标志位。如果在TCP某一个报文段中,RST的标志位=1,就说明这个报文段是RST报文段,也就是复位报文段,在某些情况下,TCP连接的一端会像另一端发送携带RST数据报文段,用来通知对方关闭连接或者重新连接。
RST报文段是请求对方连接,发送此报文段的时机有:
以上三种情况都有可能发送RST复位报文段。
如果网络异常救出出现超时或者丢包,TCP模块必须能够重传在超时时间内对方未收到的TCP报文段。
TCP模块的任务
拥塞控制
其中拥塞控制,还有TCP的流量控制,这种控制机制都是为了TCP的可靠传输设置的,拥塞控制的任务是确保子网能承载所到达的流量。这是一个全局性问题,涉及到各方面的行为(刚兴趣可以自己去搜索下,这里就不做过多介绍)。
关于拥塞控制我们进行详细的讲解:
拥塞控制的最终受控变量是发送端向网络中一次连续写入的数据量,我们称为我们称为发送窗口。不过发送窗口最终以TCP报文段来发送数据,进而发送端口就限定了连续发送的TCP报文段的数量,如图所示,发送窗口被称为SWND,这些报文段的最大长度被称为MSS发送端需要合理的选择发送窗口,如果发送窗口太小,就会出现网络延迟现象,如果发送窗口过大,就容易导致网络拥塞。接收方可以通过接收通告收窗口来控制发送端的发送窗口,但是这看起来也不够,所以在发送端引入一个称为拥塞窗口的状态变量,拥塞窗口简称CWND,接收通告窗口简称RWND。图像中就显示了拥塞控制的闭环反馈控制。
###几种拥塞控制的方法:
我们知道那个发送端维持一个拥塞窗口的状态变量,拥塞窗口简称CWND,拥塞窗口的大小取决于网络的拥塞程度,并且动态的变化。CWND的处理原则就是只要网络中没有出现拥塞现象,拥塞窗口就在大一些,以便把更多的分组发送出去。只要网络中出现拥塞,拥塞窗口就减少一些。以减少注入到网络分组中的数量。
我们现在来分析拥塞控制的算法:
慢启动:当主机开始发送数据时,如果把大量的字节注入到网络,那么就有可能引起网络拥塞。因为我们现在并不清楚网络的负载情况。所以比较好的方法就是自动去探测一下,由小到大满满增大拥塞窗口的数值,通常在刚刚开始发送报文段的时候,先把拥塞端口设置为一个最大报文段,而在每个在收到新的报文段的时候,把拥塞窗口的大小加1,按照指数规律增长,也就是增大一个最大报文段的数值。我们用同样的方法逐渐增大发送端的拥塞窗口。可以使分组注入到网络中的数据更加合理。
对应到图示中,横坐标从0->3都是满启动的状态。我们为了防止因为增大造成的网络拥塞,我们还需要设置一个满启动的ssthresh值,关于慢启动的ssthresh用法就是如果拥塞窗口小于ssthresh值,就应用慢启动算法。如果拥塞窗口大于ssthresh值,就停止应用慢启动算法。而改用拥塞避免算法
拥塞避免:拥塞避免算法为了让拥塞窗口缓慢的增长,就是每经过一个往返的时间,就把发送方的拥塞窗口加1,而不是成倍增长,这样拥塞窗口是按照线性规律缓慢增长。对应到图像中就是那个明显的拐点以后,都是拥塞避免的算法执行。
仅仅应用 慢启动和拥塞控制,不可能达到控制网络拥塞
在很多情况下,TCP发送端都可以接受到重复的确认报文段,例如TCP报文段缺失等等,发送端如果连接接收到三个重复的确认报文段,就可以判断网络中发生了拥塞。这个时候使用快速重传,快速恢复算法。快速重传算法我先要求接受端每收到一个失去的报文到,就立即发送重传确认。
拥塞发生或有三个处理不步骤:
拥塞发生后的处理过程:
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/lastdays_l/article/details/47313317