admin 管理员组

文章数量: 887021

TCP/IP和TCP,UDP

1.TCP/IP协议:        

1.1 TCP/IP协议是什么:

        很多人认为tcp/ip就是tcp和ip组成的通信协议。其实tcp/ip协议不仅仅指代tcp/ip,它是指一个由FTP,SMTP,TCP,UDP,IP,HTTP等协议构成的协议簇, 因为在这些协议中TCP协议和IP协议最具代表性,所以这些协议被称为TCP/IP协议。

1.2 面向连接和无连接:

        在了解这两者之前我们需要明白数据通过网络传递时一般会有很多条路径可以选择,以A向B传递数据为例,假设有5个路由器1-5,分布如下:

        此时A至B有如下选择:

        1:A->1->4->B     2:A->1->3->4->B     3: A->1->3->2->5->B    4.A->2->3->4->B

        5:A->2->3->1->4->B     6.A->2->5->B

        多个路由器时选择的路径是由路由器内部算法决定的。

        无连接时每个数据之间互不干扰,每次发送均有可能走上述6种路径的任意一种,假定走路径1(A->1->4->B),此时如果4停电了,或者由于其它原因不接收数据了,那么该数据包就无法正确送达,此时A只知道自己发出去了,不知道B有没有收到,而B也不知道A到底发没发数据。这就是无连接数据包丢包的原因。此外假如先后发送数据包x和数据包y,x走的路径1,y走的路径6,那么此时如果路径6传输数据很快就有可能发生后发的y比先发的x先到达B的情况,因此无连接数据包有可能乱序。但是无连接只管成功发送,不管目标通道和是否送达,因此无连接协议发送的数据包额外信息较少,一般只需包括长度和校验和,因此效率较高。可以看出无连接协议高效但是会出现丢包和乱序的情况。此外无连接可以进行一对多,多对一和多对多通信。UDP就是典型的无连接协议。

        面向连接的套接字在正式通信之前要先确定一条路径,确认该信息路径成功建立之后再发送信息,在发送信息完毕后关闭连接。这样在发送信息时保证了数据可以送达(粘包问题实际上数据已经送达了,只是在处理时出现的问题)。但是这样的代价是每发送一个数据包另一方就要回复一个内容表示已收到,导致数据包数量变大。每个数据包除了源端口和目的端口外也多出了序号,确认信号,数据偏移,控制标志窗口等信息,导致体量变大。此外即便只发送少量信息,面向连接的协议也要建立连接和断开连接,因此如果交互信息不多时建立和断开连接的成本甚至超过了信息交互的成本。可以看出面向连接是牺牲资源来换取数据包一定能送达。面向连接方式由于需要建立连接,因此每个连接仅可以进行一对一。TCP就是典型的面向连接的协议。

        总结一下就是面向连接的方式可靠但是效率低,且只能一对一。无连接方式不可靠但是效率高,可以一对多,多对多。

1.3 有状态和无状态:

        简单来说有状态就是下一次传输的报文段和上一次传输的报文段是有关系的,无状态就是下一次的请求与上一次的请求没有任何关系,是一次独立的请求。假如我们需要传顺序为1->2->3的数据包,有状态的协议传递时,如果2丢失,那么接收方会等待2,此时发送方如果在一定时间没有收到2的回复就会再次发送2,这样拿到2之后就可以进行排序。而无状态就使得丢失2可能需要全部重发,因为不知道丢的哪个。tcp通过有状态和面向连接共同保证包不乱序。

2. tcp协议:

        tcp协议是在传输层的面向连接的有状态的协议。其面向连接的特点可以看出它在传递数据前后需要建立和断开连接。tcp数据包首部有20-60字节的空间开销。

2.1 三次握手:

        三次握手是在传递数据前建立连接的过程需要进行三次数据传递:

        第一次:A向B发送syn包,想要开启连接。

        第二次:B接收到A发送的syn包,此时证明B可以收到A发送的包,因此发送对于该syn包的应答ack包,让A知道自己可以收到。但此时无法证明自己可以发包给A,因此还要发送自己的syn包给A来告知A可以向自己发数据。

        第三次:A接到B发送的消息,证明了自己可以收到B的数据,且确定B收到了自己的syn,然后向B发送B的syn的应答ack来通知B可以向自己发数据。

        由上可以分析,假入只进行第一次握手,那么A不知道B可不可以收到,完全失去了面向连接的意义。如果进行两次握手,那么只能确定A可以向B发送消息但是不能确定B可以向A发送消息,加入A是内网B是公网,那么连接就变成单向了,B无法向A发送消息。这就是必须进行三次握手的原因。

2.2 四次挥手:

        四次挥手为断开连接时进行的四次数据发送,步骤如下:

        第一次:A向B发送syn包,想要关闭连接。

        第二次:B接收到A发送的syn包,因此发送对于该syn包的应答ack包。但此时只证明A没有消息传递消息给B,但是B可能有消息传递给A。

        第三次:B没有消息传递给A,发送syn想要关闭连接。

        第四次:A收到syn,发送回应的ack给B,关闭连接。

        我们发现四次挥手多了一次数据发送,原因也好理解,因为B可能有消息传给A。

2.3 长连接和短连接:

        长连接指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接。短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接。 

        长连接可以省去多次数据传送时三次握手和四次挥手产生的开销,但是如果连接过多会导致占用资源,如果一个服务器接收成万级十万级甚至百万级的连接那么每个连接都占用一个信道,还要互相发送心跳包维持,因而起到了适得其反的效果。

        短连接不会消耗太多信道资源,但是当与相同机器有多次数据交互时会产生大量三次握手和四次挥手的开销。

2.4 面向字节流:

        tcp是面向字节流的协议,面向字节流即TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,应用程序传送的数据块太长,TCP就把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也等待积累有足够多的字节后再构成报文段发送出去。

2.5 tcp粘包:

        TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。产生原因可能在发送端或接收端,也可能都有。

        发送端原因:由于TCP协议本身的机制,如果发送的网络数据包太小,那么他本身会启用Nagle算法对较小的数据包进行合并,然后等即将超时或者累积数据足够大再发送。那么这样的话,另一方接收到消息的时候新的数据包紧贴着旧数据包的尾,使得接收端无法分割数据包。

        接收端原因:接收数据时放到缓冲区中,如果消息没有被及时从缓存区取走,下次在取数据的时候可能就会出现一次取出多个数据包的情况,造成粘包现象。

2.6 tcp粘包的解决:

        首先,短连接不需要考虑tcp粘包。其次如果发送的消息本就是连续的,比如A向B发送一个文件的内容,一次发送若干个字节,那么此时粘包就无需考虑,因为两个包的内容本来就该首尾相连。

        发送端想要解决tcp粘包可以关闭Nagle算法,这样数据就将一次一发,不会产生该现象。

        仅就传输层来讲接收端无法解决tcp粘包,但是应用层可以规定数据格式,比如发送每个数据包时在首部固定位数(比如4位)存储长度,这样接收时可以通过长度来分割每个包。

        关闭Nagle算法会产生额外次数的三次握手和四次挥手。规定数据格式会有额外的空间来存储长度。如果在相对适合长连接的场景规避粘包使用短连接也会产生额外开销。因此除非传输连续文件,否则解决tcp粘包一定会产生额外开销,导致效率不通程度的降低。

2.7 tcp的优缺点:

        上面可以看出tcp的优缺点。tcp作为面向连接的有状态的协议,除了齐聚这二者优缺点外还有粘包问题的缺点。简单的说优点就是安全可靠,不会丢包和乱序,缺点就是开销大(粘包问题的解决本质也是产生额外开销),只能一对一。

3.UDP协议:

        udp是在传输层的无连接无状态的协议,其首部仅有8字节开销。从这些可以看出UDP具有快,高效,开销小的优点,但是也可能产生丢包和乱序的问题。UDP是面向数据报的协议。其不合并或拆分报文,报文多长它就发送多长。同样因为无连接所以会产生丢包。由于无状态所以会产生乱序。

        有很多方式可以不通程度的解决udp丢包现象,诸如UDT,KCP等。

本文标签: TCPIP和TCP UDP