TCP/IP协议下三层协议(二)----传输层协议

1.UDP用户数据报协议
首先,说明UDP的几个主要特点:
①UDP是无连接的;
②UDP尽最大努力交付,但不保证数据可靠性;
③UDP是面向报文的;
④UDP没有拥塞控制(网络出现拥塞状况并不会导致源主机的发送速率降低);
⑤UDP支持一对一,一对多,多对一与多对多的交互通信;
⑥首部开销小;

TCP/IP协议下三层协议(二)----传输层协议_第1张图片

UDP的数据段格式很简单,它的报头是定长(因此UDP协议报头信息中无需加入报头长度的信息),其报头信息包括源端口号和目的端口号,UDP整个报文长度以及UDP检验和
这里解释一下端口号的作用:对于任何一个网络进程,IP地址+端口号是他的唯一标识信息,而一般的网络通信当中,通信双方分为客户端和服务器,由我们的客户端主动发出请求,而服务器则是被动的等待,接收和应答,而正因为我们的客户端需要向服务器主动发送请求,所以它必须要知道服务器的IP地址和端口号,所以对于客户端而言,它的端口号可以是任意的,由用户端自由分配一个空闲的端口号,但对于服务器而言,它的端口号则必须是固定的,而且是被所有人所知晓的(例如:HTTP服务对应端口号80,HTTPS则对应443,FTP对应21),在使用客户端程序的时候,必须明确指定服务器IP地址与端口号(在/etc/services文件中列出了所有被众所周知的服务端口号以及其对应的传输协议)

对于UDP协议而言,这个传输协议不面向连接,也不会保证传输的可靠性,发送端只管将上层的数据报文进行封装,传给下层的IP协议,而对于接收端则只管对IP协议层发送过来的数据进行报头和有效载荷信息分离即可,至于数据包有没有丢失,接收数据的顺序对不对,UDP协议并不会处理,而这自然就得轮到上层应用层进行处理这些问题了,正因为UDP协议的这种特性,所以一般使用UDP的网络服务都比较简单,数据量少,对于数据的可靠性要求不高,与之相对的TCP协议就恰恰相反,对于可靠性有着相当的要求,正因如此也就更加复杂

2.TCP传输控制协议
首先介绍TCP的主要特点:
①TCP是面向连接的(即在应用TCP协议时操作系统会对连接进行描述,创建对应的结构体来进行维护管理连接);
②TCP是面向字节流的;
③每条TCP连接只能是一对一的;
④TCP提供全双工通信;
⑤TCP提供可靠交付的服务;
TCP/IP协议下三层协议(二)----传输层协议_第2张图片

对于TCP协议的数据段格式中的报头信息:
16位源端口号和16位目的端口号表示源主机对应端口号与目的主机对应端口号;
32位序号表示对于发送端而言,本报文段所发送的第一个字节的序号(对于TCP协议而言,它对传送的数据的每个字节都进行按顺序编号),与之相对的就是32位确认序号(假设该字段值为n),它表示对于接收端而言,期望下一个收到发送端发送的字节序号,换言之,在确认序号之前的信息已经确认收到【对于序号与确认序号这两个字段,它们一来保证数据的不丢失,二来保证了数据在发送端是如何发送的,在接收端就如何接收,顺序不会混乱,这是保证了TCP协议的可靠性传输】;
4位首部长度也叫数据偏移,单位为字(4字节),范围是5~15,表示首部最小长度为20字节,最大为60字节(保证了首部与有效载荷部分能够有效区分);6位保留字段留待后用,目前置为0;16位窗口大小表示一个缓冲区的大小,而这个缓冲区则是自己作为接收端的时候,接收缓冲区的大小,这个字段的目的在于让对方知道我方现在的接收缓冲区的大小,协同发送端和接收端双方接收数据(由于通信双方会因为各种原因导致其发 送与接收数据的能力有所不同,倘若发送端的发送数据能力较强,而接收端的读取数据能力较弱,则会导致缓冲区满了而发送端还在发送数据,而已满的缓冲区万万不能用新数据将还未被读取的数据进行覆盖,那么必然导致新发送过来的数据不能被接收,而窗口大小这个字段的作用则是在于让发送端知道接收端当前的接收缓冲区的大小(能接收数据的能力有多大),从而做出调整(当窗口大小为0时,发送端不再发送数据,等待接收端读数据,通过轮循的方式在一段时间后向接收端发送对应信号询问缓冲区大小,而接收端在响应时告诉发送端自己的接收缓冲区当前大小,以判断是否能够发送数据));
16位检验和用于检验数据是否发送正确;16位紧急指针表示本报文段的紧急数据的字节数;
除了上述的字段,还有6位控制位:
①URG表示置1时后面的16位紧急指针字段有效,说明此报文段中有紧急数据(类似于高优先级数据),需要优先传输,发送端会将紧急数据提到报文数据的最前面以保证其能够优先传输(紧急指针表明了有多少字节紧急数据,而这样一来从数据起始处偏移对应字节这个区域就是紧急数据),而当接收端检测到所接收的数据报中该位被置1,则去检测紧急指针字段,分析有多少字节是需要紧急处理的,对这些数据进行优先处理;
②ACK表示置1时确认序号字段有效,在TCP连接建立后所有的ACK字段均要置为1;
③PSH表示置1时表示发送端想立即得到接收端的响应,所以立即创建一个报文段将数据发送出去,而不会等到缓冲区满才发送,而对于接收端而言,当检测到PSH=1时,则将得到的报文段数据立即交给上层应用进行处理,不在等待缓冲区满才向上交付;
④RST表示当前TCP连接可能出现了严重差错,必须得释放连接,然后重新建立连接,此时将RST置1即可完成复位,除此之外,这个标志位还可以用来拒绝一个非法的报文段或拒绝一个连接;
⑤SYN表示在建立连接时用来同步序号,与ACK一起,当SYN=1,ACK=0时,表明这是一个连接请求的报文,若对方同意连接,则会响应SYN=1,ACK=1,所以SYN置1表示这是一个请求连接或连接响应报文;
⑥FIN用于释放一个连接,当FIN置1时,表示数据发送完毕,请求终止连接;

以上就是TCP首部信息的大致介绍,而对于TCP协议而言,由于它是面向连接的,TCP的连接建立与释放就尤为关键:
TCP/IP协议下三层协议(二)----传输层协议_第3张图片

(1)三次握手----建立连接
第一次握手:由客户端主动发出连接请求,发送请求建立连接的报文,将SYN设为1,占用一个序号1000(TCP规定SYN报文段不携带数据,但要消耗一个序号),还有一点mss代表最大报文段长度,如果一个报文段太大,那么当它封装成帧后对于链路层而言则是超过了它的最大帧长度MTU,这样一来就必须在IP层进行分片,这会大大降低效率,所以mss表示建议服务器发送的段长度不要超过这个值;
第二次握手:服务器收到了客户端发来的连接请求,若同意建立连接,则向客户端发送连接应答响应,将SYN设为1,ACK设为1,并且确认序号设为1001(表示已经收到客户端发来的序号为1000的数据,希望客户端下次发送序号为1001的数据),同时该响应报文段占用一个序号8000,并且将自己的最大报文段长度发送给客户端(理由同上);
第三次握手:客户端在成功收到来自服务器的请求响应之后,再次向服务器发送信息,而此次发送的是响应确认收到的信息,将ACK设为1,并且将确认序号设为8001(表示已经收到服务器发来的序号为8000的数据,希望服务器下次发送序号为8001的数据 ),当服务器成功收到来自客户端的确认信息之后,那么此时服务器与客户端之间的连接随即建立;

事实上,在第二次握手成功后,客户端就已经认为成功建立了连接,并且建立对应的数据结构去维护连接,但是这个时候服务器却认为连接还没能建立,并没有对应的数据结构建立来维护这个连接,而这也是为什么在建立连接的时候只能是三次握手,而不能是两次握手或者是四次握手的关键:
若没有第三次握手,那么第一次握手成功后,服务器就认为已经建立了连接,并且会向客户端发送响应信息,但是如果这个时候由服务器发送的响应信息在发送过程中出现了丢失,导致客户端没能收到服务器的响应,第二次握手失败,那么客户端就会认为连接并没有建立,但此时服务器却认为连接建立了,并创建了对应的数据结构来维护这个连接,这样一来这个连接显然是无效的,而对于服务器而言,若在服务器中存在大量的无效连接,这必然会降低服务器的性能,甚至影响服务器的正常服务;而对于三次握手而言,在第二次握手成功后,服务器并不认为连接建立了,而是客户端认为连接成功建立,并在第三次握手的时候客户端向服务器发送确认收到响应信息,若此时确认信息成功到达服务器,则服务器建立连接,否则服务器就认为连接未能建立,并在一段时间后认为客户端未能收到自己的响应信息,并再次向客户端发送响应信息,这样一来服务器当中就不会存在大量的无效连接从而影响服务器的正常工作(可能有人会认为这样一来,客户端中不就会存在无效连接了吗,但是对于客户端而言,一来无效连接的数量肯定不会多,二来客户端不会像服务器一样向他人提供服务,所以就算有影响也是微乎其微的);然而至于四次握手或更多,三次握手能解决的问题为什么要进行多余的握手呢,这也是一种变相的降低效率

综上,三次握手建立连接期间完成的工作就是协调通信双方的相关信息(彼此双方的窗口大小,彼此双方的最大数据段mss大小,以及建立各自的描述连接的数据结构等)
(2)四次挥手----释放连接                      http://blog.csdn.net/wenqiang1208/article/details/72673618
第一次挥手:对于通信双方而言,都可以在数据传输结束后首先释放连接,这里我们假定客户端先释放连接,将FIN置1,表示此时客户端的数据已经发送完毕,请求释放连接,发送相应的请求报文段,并将ACK设为1,确认序号为8011,并且占用一个序号1021,但此时不携带数据;
第二次挥手:服务器在接收到客户端的释放连接请求时,向客户端发送信息,将ACK设为1,并将确认序号设为1022,表示1022序号之前的数据已准确收到,期望下次能收到序号为1022的数据,而当客户端收到服务器发回的响应后,此时TCP连接将进入半关闭状态,即客户端不再向服务器发送数据,但如果服务器向客户端发送数据,客户端依旧得接收,也就是说此时客户端虽不会再进行数据发送,但它依旧会维护数据结构来保证连接;
第三次挥手:服务器在自己的数据发送完毕后,向客户端发送释放连接的请求,将FIN置1,ACK置1,占用一个序号8011,但此时不携带数据,并且将确认序号设为1022;
第四次挥手:在接收到服务器的释放连接请求后,处于半关闭状态的客户端向服务器发送确认收到请求的响应,并发送给服务器,将ACK设为1,将确认序号设为8012,但此时客户端作为主动请求释放连接的一方,它的连接并未释放,而是进入TIME_WAIT状态,并在此状态等上2msl时间后,客户端连接才会释放(这里处于TIME_WAIT状态进行等待不释放连接的目的在于确保最后一次的ACK响应能够成功被服务器接收,在丢失的情况下进行重发);而对于服务器而言,在它收到ACK应答的时候,服务器的连接就已经释放;

以上便是释放连接时的四次挥手,对于TCP协议的通信双方而言,要断开连接必须双方均断开连接

(3)前面说过TCP通信双方在建立连接之处,会对双方的一些信息进行协调,其中有一项就是彼此双方的窗口大小,对于窗口大小表示接收数据缓冲区的大小,代表某一时刻各自接收数据的能力,这一项信息在TCP通信从三次握手开始到四次挥手接收,始终是需要让对方知道的,而它也是TCP通信用来作为进行流量控制的一项机制(通信双方的数据发送速率存在快慢差异),由于底层采用类似循环队列的数据结构,窗口的大小范围类似从左向右滑动,所以这项机制也叫作“滑动窗口”


补充:TCP的常见定时器
参考链接: http://blog.csdn.net/wenqiang1208/article/details/72673030
                 http://blog.csdn.net/apn172/article/details/8034242
1.连接建立定时器
在发送SYN报文段建立一条新连接时启动。如果没有在75S内收到响应,连接建立将终止。

2.重传定时器
为了控制丢失的报文段或丢弃的报文段,也就是对报文段确认的等待时间。当TCP发送报文段时,就创建这个特定报文段的重传计时器,可能发生两种情况:若在计时器超时之前收到对报文段的确认,则撤销计时器;若在收到对特定报文段的确认之前计时器超时,则重传该报文,并把计时器复位。重传定时器的值(即TCP等待对端确认的时间)是动态计算的,取决于TCP为该连接测量的往返时间和该报文段 已被重传的次数。

3.延迟ACK定时器
在TCP收到必须被确认但无需马上发出确认的数据设定。TCP等待200ms后发送确认响应。如果,在这200ms内,有数据要在该连接上发送,延迟的ACK响应就可随着数据一起发送回对端,称为捎带确认。

4.持续定时器
对于TCP通信双方互相发送数据,当对方的窗口大小为0时,另一方将停止发送数据,此时将启动持续定时器进行等待对端从接收缓冲区中读数据,当定时器超时后,向对端发送一段询问报文并且启动重传定时器,询问此时对端的窗口大小,若对端响应发送报文告诉窗口大小不为0,则随即重新开始向对端发送数据,若窗口大小仍为0,那么将持续定时器的设定值加倍并重启等待,如果在重传定时器超时还未收到对端的响应,那么根据重传定时器的原理,进行询问报文的重发;

5.保活定时器
为了应对两个TCP连接间出现长时间的没有数据传输的情况。如果客户已与服务器建立了TCP连接,但后来客户端主机突然故障,则服务器就不能再收到客户端发来的数据了,而服务器肯定不能这样永久地等下去,保活定时器就是用来解决这个问题的。服务器每收到一次客户端的数据,就重新设置保活定时器,通常为2小时,如果2小时没有收到客户端的数据,服务端就发送一个探测报文,以后每隔75秒发送一次,如果连续发送10次探测报文段后仍没有收到客户端的响应,服务器就认为客户端出现了故障,就可以终止这个连接。

6.FIN_WAIT_2定时器
当某个连接从FIN_WAIT_1状态(第一次挥手成功后主动断开连接的一端所处状态)变迁到FIN_WAIT_2状态(即第二次挥手成功之后主动断开连接的一端所处状态--半关闭状态),并且能再接收任何新数据时,FIN_WAIT_2定时器启动,设为10分钟。定时器超时后,重新设为75S,第二次超时后连接被关闭。加入这个定时器的目的是为了避免如果对端一直不发送FIN,某个连接会永远滞留在FIN_WAIT_2状态(半关闭状态)。

7.TIME_WAIT定时器
一般也称为2MSL定时器。MSL指最大报文段生存时间。主要发生在TCP释放连接四次握手中,主动关闭连接的那一方最后进入的状态,设置的时间为2MSL设置这个计时器的目的:
一是为了保证主动方发送的最后一个ACK报文段能够到达,2MSL(报文段最大生存时间)等待时间保证了重发的FIN会被主动关闭的一段收到且重新发送最后一个ACK。
二是防止已失效的连接请求报文段出现在新的连接中,TCP规定在TIME_WAIT状态,不能建立新的连接,即主动断开连接的一方连接在此状态期间不会被释放,资源依旧被占用。既然TIME_WAIT状态维持2MSL,这就保证了一个旧连接上发送的分组及其应该在 2MSL内都会消失,不会对于新的连接造成干扰。

你可能感兴趣的:(Linux随笔,网络编程)