TCP和UDP通讯的特色
不一样主机上进程与进程之间的数据传输,根据数据的大小可分为两种可能的情形:mysql
- 待发送数据较短,单个数据包便可发送完成
- 待发送数据较长,须要划分红多个数据包发送
这两种不一样的数据传输情形,正对应UDP和TCP两种协议:一个数据包能完成发送的使用UDP协议,分包发送的使用TCP协议。但注意,这里的划分方式并不严谨,UDP发送的数据并不必定短(无论有多长数据,UDP都会总体原封不动的看成一个包传输),TCP发送的数据也并不必定长,之因此如此划分是为了稍后方便解释这两个协议的特性sql
若是采用分包传输的机制,也就是TCP协议,就须要将待发送的数据划分红多个数据包来发送,一边划分一边放入TCP套接字的Send Buffer,同时还会对划分的每一个数据包进行编号,以便校验数据包的前后顺序,同时还能根据序号检测是否丢失须要重传数据包。Send Buffer中有了数据包后,就能够进入下一层网络层,而后经过网络发送给目标主机,因此,采用TCP通讯来传输数据时,就像水流同样,数据包从源端的应用层流到目标端,中间的任何一个层次均可能已经有了数据。因此,TCP数据传输是数据流模式缓存
由于有不少数据包要发送,因此在划分数据包以前就须要先在两端主机之间创建好一个TCP的链接,以便让或许全部的数据包都经过这个链接来传输,因此TCP通讯是面向链接的。既然是面向链接的,那么源端和目标端均可以借此链接来发送数据,因此TCP通讯是双向的,或者说是全双工的。既然是双向通讯,那么链接的每一端都须要有发送者和接收者,一端的发送者发送的数据被另外一端的接收者接收。为了保证每一端的收、发互不影响,每端都采用两个TCP套接字的缓存:读缓存和写缓存,也成为发送缓存或接收缓存。某端发送数据时,将划分的数据包放入Send Buffer,经过网络发送给目标主机后,放入对方的Recv Buffer,另外一端发送数据也如此网络
有了链接,双方就能够根据这个链接来作一些控制,协商一些链接的属性,好比一个包最大多少个字节,并且发送方能够根据链接来判断是否比较阻塞(拥塞)或不太稳定从而调整发送速度,这是拥塞控制。接收方若是发现接收速度或数据处理速度跟不上对方的发送速度,能够通知对方下降发送速度甚至短暂中止发送oracle
若是待发送数据只想用一个数据包发送,那么采用UDP传输协议。UDP传输时不会对数据进行分包,固然也就不须要编号,由于只有一个包,只需发送一次,因此UDP不须要创建链接。由于没有链接,因此只能是单向传输,且没法很好的判断数据包是否到达目标。由于没有链接,也没法像TCP同样能够借此来作拥塞控制。但也正由于UDP不须要链接,不须要分包,因此UDP传输效率比TCP要高,且传输期间占用的系统资源也要远小于TCPssh
UDP协议
UDP(User Datagram Protocol)是用户数据报协议,是OSI的传输层协议。它只是比IP数据包多提供了一些不多功能,好比添加端口标识不一样的应用层协议、差错校验等
UDP的主要特色包括:tcp
- UDP是无链接的,即发送数据以前不须要和对方先创建好链接(因此也没有关闭链接的过程),所以效率比较高
- UDP只能尽可能保证数据能够到达对方,但没法保证可靠的交付。主要仍是由于没有创建链接,数据丢失后没法重传
- UDP是面向数据报的。当应用层采用UDP协议时,UDP将数据添加首部后直接给网络层,它不会合并也不会拆分,而是应用层给多少数据,UDP就包装多少数据,包装后的数据称为数据报。传输时以数据报为单位,一次传输一个数据报文。接收到UDP报文时,UDP解封后直接将整个数据交给应用层。因此,对于使用UDP协议的程序,必须选择大小合适的报文,若是报文太大,则在IP层会对其进行分片,这会致使IP层的效率极低
- UDP首部开销很小,只有8个字节,而TCP的首部有20个字节,相比TCP而言,UDP的效率要高一些
- UDP没有拥塞控制,在网络出现拥塞的时候,源主机不会所以而下降发送速率,因此UDP的实时性比较好,因此,对于容许丢失一些数据,但又要求高实时性的场景,UDP更为适合
- 差错校验功能有限,在校验后发现不一致,将直接丢弃数据报
UDP数据报包含两个部分ide
- 数据部分:首部部分很是简单,共8个字节4字段,每一个字段2字节
- 首部部分
屏幕快照 2020-07-27 16.56.05
屏幕快照 2020-07-27 16.56.52
TCP首部
- 源端口、目标端口:计算机上的进程要和其余进程通讯是要经过计算机端口的,而一个计算机端口某个时刻只能被一个进程占用,因此经过指定源端口和目标端口,就能够知道是哪两个进程须要通讯。源端口、目标端口是用16位表示的,可推算计算机的端口个数为2^16个
- 序列号:表示本报文段所发送数据的第一个字节的编号。在TCP链接中所传送的字节流的每个字节都会按顺序编号。因为序列号由32位表示,因此每2^32个字节,就会出现序列号回绕,再次从 0 开始
- 确认号:表示接收方指望收到发送方下一个报文段的第一个字节数据的编号。也就是告诉发送方:我但愿你(指发送方)下次发送的数据的第一个字节数据的编号为此确认号
- 数据偏移:表示TCP报文段的首部长度,共4位,因为TCP首部包含一个长度可变的选项部分,须要指定这个TCP报文段到底有多长。它指出 TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远。该字段的单位是32位(即4个字节为计算单位),4位二进制最大表示15,因此数据偏移也就是TCP首部最大60字节
- URG:表示本报文段中发送的数据是否包含紧急数据。后面的紧急指针字段(urgent pointer)只有当URG=1时才有效
- ACK:表示是否前面确认号字段是否有效。只有当ACK=1时,前面的确认号字段才有效。TCP规定,链接创建后,ACK必须为1,带ACK标志的TCP报文段称为确认报文段
- PSH:提示接收端应用程序应该当即从TCP接收缓冲区中读走数据,为接收后续数据腾出空间。若是为1,则表示对方应当当即把数据提交给上层应用,而不是缓存起来,若是应用程序不将接收到的数据读走,就会一直停留在TCP接收缓冲区中
- RST:若是收到一个RST=1的报文,说明与主机的链接出现了严重错误(如主机崩溃),必须释放链接,而后再从新创建链接。或者说明上次发送给主机的数据有问题,主机拒绝响应,带RST标志的TCP报文段称为复位报文段
- SYN:在创建链接时使用,用来同步序号。当SYN=1,ACK=0时,表示这是一个请求创建链接的报文段;当SYN=1,ACK=1时,表示对方赞成创建链接。SYN=1,说明这是一个请求创建链接或赞成创建链接的报文。只有在前两次握手中SYN才置为1,带SYN标志的TCP报文段称为同步报文段
- FIN:表示通知对方本端要关闭链接了,标记数据是否发送完毕。若是FIN=1,即告诉对方:“个人数据已经发送完毕,你能够释放链接了”,带FIN标志的TCP报文段称为结束报文段
- 窗口大小:表示如今容许对方发送的数据量,也就是告诉对方,从本报文段的确认号开始容许对方发送的数据量,达到此值,须要ACK确认后才能再继续传送后面数据,由Window size value * Window size scaling factor(此值在三次握手阶段TCP选项Window scale协商获得)得出此值
- 校验和:提供额外的可靠性
- 紧急指针:标记紧急数据在数据字段中的位置
- 选项部分:其最大长度可根据TCP首部长度进行推算。TCP首部长度用4位表示,选项部分最长为:(2^4-1)*4-20=40字节
TCP首部常见选项:memcached
- 最大报文段长度:Maxium Segment Size,MSS,一般1460字节
- 窗口扩大:Window Scale
- 时间戳: Timestamps
- 最大报文段长度MSS(Maximum Segment Size)指明本身指望对方发送TCP报文段时那个数据字段的长度。好比:1460字节。数据字段的长度加上TCP首部的长度才等于整个TCP报文段的长度。MSS不宜设的太大也不宜设的过小。若选择过小,极端状况下,TCP报文段只含有1字节数据,在IP层传输的数据报的开销至少有40字节(包括TCP报文段的首部和IP数据报的首部)。这样,网络的利用率就不会超过1/41。若TCP报文段很是长,那么在IP层传输时就有可能要分解成多个短数据报片。在终点要把收到的各个短数据报片装配成原来的TCP报文段。当传输出错时还要进行重传,这些也都会使开销增大。所以MSS应尽量大,只要在IP层传输时不须要再分片就行。在链接创建过程当中,双方都把本身可以支持的MSS写入这一字段。 MSS只出如今SYN报文中。即:MSS出如今SYN=1的报文段中
- MTU和MSS值的关系:MTU=MSS+IP Header+TCP Header
- 通讯双方最终的MSS值=较小MTU-IP Header-TCP Header
- 窗口扩大
- 为了扩大窗口,因为TCP首部的窗口大小字段长度是16位,因此其表示的最大数是65535。可是随着时延和带宽比较大的通讯产生(如卫星通讯),须要更大的窗口来知足性能和吞吐率,因此产生了这个窗口扩大选项
- 时间戳
- 能够用来计算RTT(往返时间),发送方发送TCP报文时,把当前的时间值放入时间戳字段,接收方收到后发送确认报文时,把这个时间戳字段的值复制到确认报文中,当发送方收到确认报文后便可计算出RTT。也能够用来防止回绕序号PAWS,也能够说能够用来区分相同序列号的不一样报文。由于序列号用32为表示,每2^32个序列号就会产生回绕,那么使用时间戳字段就很容易区分相同序列号的不一样报文
屏幕快照 2020-07-27 17.00.04
TCP协议PORT
- 传输层经过port号,肯定应用层协议
- Port number:
- tcp:传输控制协议,面向链接的协议;通讯前须要创建虚拟链路;结束后拆除链路
- udp:User Datagram Protocol,无链接的协议
- IANA:互联网数字分配机构(负责域名,数字资源,协议分配)
- 0-1023:系统端口或特权端口(仅管理员可用) ,众所周知,永久的分配给固定的系统应用使用,22/tcp(ssh), 80/tcp(http), 443/tcp(https)
- 1024-49151:用户端口或注册端口,但要求并不严格,分配给程序注册为某应用使用,1433/tcp(SqlServer), 1521/tcp(oracle),3306/tcp(mysql),11211/tcp/udp (memcached)
- 49152-65535:动态端口或私有端口,客户端程序随机使用的端口
- 其范围的定义:/proc/sys/net/ipv4/ip_local_port_range
可靠传输:丢失重传和窗口滑动
基于TCP链接传输数据是可靠的,它保证数据不丢失,且能按照正确的顺序被对方接收。这里涉及到一些比较重要的机制,简单描述下:
首先假设只有一个数据包须要传输,若是这个包没有丢失,也没有出现差错,那么一切都正常,但若是传输的这个数据包丢失了或出现差错了,那么就要求发送方重传这个包。为了可以重传这个包,发送方须要遵照一些简单的规则:性能
- 保留这个包不能删除,以便出现问题时直接重传
- 发送这个包后中止,等待接收方回复确认包
- 设置一个定时器,在指定时间内若是没有收到接收方的回复,则认为包丢失,因而重传该包
- 若是收到确认包以后,开始传输下一个包
遵照这几个规则能够保证基于TCP链接传输数据是可靠的,不会丢失任何数据,可是这样的效率很是低下,每次发送数据包都须要等待,因而,改进这种方案,不是一次发送一个包就等待,而是一次性发送多个包,而后进入等待。如今规则改进:
- 一次发送4个包(这是假设值),发送后保留4个包,以便出现问题时重传
- 发送4个包后中止,等待接收方恢复确认包
- 设置一个定时器,在指定时间内若是没有收到接收方的回复,则重传4个包
- 接收方接收到包以后,若是4个包一切正常,则回复,让发送方发送后续数据包
- 若是接收方发现中间第3个包出现问题,则发送确认,确认号是第3个包的起始字节,也就是说,接收方只接受到了前两个包,后面两个包须要重传
- 发送方根据收到的确认号,知道要重传第三个包,因而将保留下来的4个包中的前两个剔除,并加入两个新的包,因而本次再次发送4个包。本次发送的四个包中,前两个是重传包,后两个是新包
- 接收方收到新的4个包后,若是一切正常,则确认给发送方
根据这种规则传输数据,比以前每发送一次包就停下来等待,效率要高不少。并且,一次发送多少个包是能够更改的,这取决于窗口(Window)的大小。假如一个包的大小是100字节,窗口大小是400字节,那么一次就能发送4个包,若是窗口大小是1000字节,一次就能发送10个包。每次发送一个窗口中的包以后,若是接收到接收方的确认信息,那么窗口中的全部包都将滑出窗口,并存放新的数据包。若是中间某个包出现了差错,则只滑出那部分已确认接收的包,并放入对应个数的新数据包
TCP链接创建时,接收方会和发送方协商窗口应设置为多大,这样发送方就会根据这个窗口大小决定一次发送多少个包。而且,接收方能够随时动态调整窗口的大小,从而限制发送方发送数据包的速度,实现流量的控制。这种窗口滑动的模式虽然已经足够高效了,可是仍不足,好比窗口大小是4个包的大小,接收方发现第二个包出错了,会致使发送方重传这4个包中的3个,效率较低,更加的处理方式是只重传哪一个出错的包。这就是改进的传输模式,实现方式在接收方回复确认信息给发送方时,在其回复包的TCP首部可选字段假如一个选项,来指明已经接收到的字节的起始和接收位置