表示层:图像、视频编码解,数据加密;会话层:建立会话,如session认证、断点续传。
不使用「两次握手」和「四次握手」的原因:
对于握手:握手需要同步双方通信时的初始序列号。序列号能够保证数据包不重复、不丢弃和按序传输。(第三次握手必要性:假设服务端的确认丢失,连接并未断开,客户机超时重发连接请求,这样服务器会对同一个客户机保持多个连接,造成资源浪费。)序列号在 TCP 连接中占据着非常重要的作用,当客户端发送携带「初始序列号」的 SYN
报文的时候,需要服务端回一个 ACK
应答报文,表示客户端的 SYN 报文已被服务端成功接收,那当服务端发送「初始序列号」给客户端的时候,依然也要得到客户端的应答回应,这样一来一回,才能确保双方的初始序列号能被可靠的同步。
对于挥手:TCP是双工的,所以发送方和接收方都需要发送FIN 连接释放报文和接收ACK应答。只不过有一方是被动的,进入了 CLOSE-WAIT 状态。这个状态是为了发送还未传送完毕的数据,传送完毕之后会发送 FIN 连接释放报文。
FIN_WAIT_2:半关闭状态,发送断开请求一方还有接收数据能力,但已经没有发送数据能力。
CLOSE_WAIT状态:被动关闭连接一方接收到FIN包会立即回应ACK包表示已接收到断开请求,被动关闭连接一方如果还有剩余数据要发送就会进入CLOSED_WAIT状态。
TIME_WAIT状态:又叫2MSL等待状态,如果客户端直接进入CLOSED状态,如果服务端没有接收到最后一次ACK包会在超时之后重新再发FIN包,此时因为客户端已经CLOSED,所以服务端就不会收到ACK而是收到RST。所以TIME_WAIT状态目的是防止最后一次握手数据没有到达对方而触发重传FIN准备的。在2MSL时间内,同一个socket不能再被使用,否则有可能会和旧连接数据混淆(如果新连接和旧连接的socket相同的话)。
超时重传:发送端发送报文后若长时间未收到确认的报文则需要重发该报文。可能有以下几种情况:
发送的数据没能到达接收端,所以对方没有响应。
接收端接收到数据,但是ACK报文在返回过程中丢失。
接收端拒绝或丢弃数据。
RTO:从上一次发送数据,因为长期没有收到ACK响应,到下一次重发之间的时间。就是重传间隔。
通常每次重传RTO是前一次重传间隔的两倍,计量单位通常是RTT。例:1RTT,2RTT,4RTT,8RTT......
重传次数到达上限之后停止重传。
RTT:数据从发送到接收到对方响应之间的时间间隔,即数据报在网络中一个往返用时。大小不稳定。
目的是接收方通过TCP头窗口字段告知发送方本方可接收的最大数据量,用以解决发送速率过快导致接收方不能接收的问题。所以流量控制是点对点控制。
TCP是双工协议,双方可以同时通信,所以发送方接收方各自维护一个发送窗和接收窗。
发送窗:用来限制发送方可以发送的数据大小,其中发送窗口的大小由接收端返回的TCP报文段中窗口字段来控制,接收方通过此字段告知发送方自己的缓冲(受系统、硬件等限制)大小。
接收窗:用来标记可以接收的数据大小。
TCP是流数据,发送出去的数据流可以被分为以下四部分:已发送且被确认部分 | 已发送未被确认部分 | 未发送但可发送部分 | 不可发送部分,其中发送窗 = 已发送未确认部分 + 未发但可发送部分。接收到的数据流可分为:已接收 | 未接收但准备接收 | 未接收不准备接收。接收窗 = 未接收但准备接收部分。
发送窗内数据只有当接收到接收端某段发送数据的ACK响应时才移动发送窗,左边缘紧贴刚被确认的数据。接收窗也只有接收到数据且最左侧连续时才移动接收窗口。
拥塞控制目的是防止数据被过多注网络中导致网络资源(路由器、交换机等)过载。因为拥塞控制涉及网络链路全局,所以属于全局控制。控制拥塞使用拥塞窗口。
TCP拥塞控制算法:
慢开始 & 拥塞避免:先试探网络拥塞程度再逐渐增大拥塞窗口。每次收到确认后拥塞窗口翻倍,直到达到阀值ssthresh,这部分是慢开始过程。达到阀值后每次以一个MSS为单位增长拥塞窗口大小,当发生拥塞(超时未收到确认),将阀值减为原先一半,继续执行线性增加,这个过程为拥塞避免。最终拥塞窗口会收敛于稳定值。
流量控制属于通信双方协商;拥塞控制涉及通信链路全局。
流量控制需要通信双方各维护一个发送窗、一个接收窗,对任意一方,接收窗大小由自身决定,发送窗大小由接收方响应的TCP报文段中窗口值确定;拥塞控制的拥塞窗口大小变化由试探性发送一定数据量数据探查网络状况后而自适应调整。
实际最终发送窗口 = min{流控发送窗口,拥塞窗口}。
建立连接(标志位):通信前先建立全双工的连接,确认通信实体存在。
序号机制(序号、确认号):确保了数据是按序、完整到达。tcp会按最大传输单元(MTU)合理分片,接收方会缓存未按序到达的数据,重新排序后交给应用层。而UDP:IP数据报大于1500字节,大于MTU。这个时候发送方的IP层就需要分片,把数据报分成若干片,使得每一片都小于MTU。而接收方IP层则需要进行数据报的重组。由于UDP的特性,某一片数据丢失时,接收方便无法重组数据报,导致丢弃整个UDP数据报。
数据校验(校验和):TCP报文头有CRC校验和,用于校验报文是否损坏。
超时重传(定时器):保证因链路故障未能到达数据能够被多次重发。
窗口机制(窗口):提供流量控制,避免过量发送。
流量控制:当接收方来不及处理发送方的数据,能通过滑动窗口,提示发送方降低发送的速率,防止包丢失。
拥塞控制:当网络拥塞时,通过拥塞窗口,减少数据的发送,防止包丢失。
原因是 TCP 有可变长的「选项」字段,而 UDP 头部长度则是不会变化的,无需多一个字段去记录 UDP 的首部长度。
TCP 的连接状态查看,在 Linux 可以通过 netstat -napt
命令查看。可以看到TCP协议,源地址+端口,目标地址+端口,连接状态,Web服务的进程PID和进程名称
服务器通常固定在某个本地端口上监听,等待客户端的连接请求。客户端 IP 和 端口是可变的,其理论值计算公式为客户端的IP数乘客户端的端口数。
对 IPv4,客户端的 IP 数最多为 2
的 32
次方,客户端的端口数最多为 2
的 16
次方,也就是服务端单机最大 TCP 连接数,约为 2
的 48
次方。当然,服务端最大并发 TCP 连接数远不能达到理论上限。
ulimit
配置文件描述符的数目;另一个是内存限制,每个 TCP 连接都要占用一定内存,操作系统是有限的。UDP为了实时性,抛弃了可靠性和公平性。TCP为了可靠性和公平性牺牲了实时性。UDP和TCP全世界广泛应用的今天,大量网络带宽被UDP占用,而TCP由于内置的拥塞控制、流量控制机制而被迫为UDP让路。
DNS
、SNMP
等,视频、音频等多媒体通信,广播通信起始 ISN
是基于时钟的,每 4 毫秒 + 1,转一圈要 4.55 个小时。
RFC1948 中提出了一个较好的初始化序列号 ISN 随机生成算法。
ISN = M + F (localhost, localport, remotehost, remoteport)
M
是一个计时器,这个计时器每隔 4 毫秒加 1。F
是一个 Hash 算法,根据源 IP、目的 IP、源端口、目的端口生成一个随机数值。要保证 Hash 算法不能被外部轻易推算得出,用 MD5 算法是一个比较好的选择。客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:
确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。
TCP 是一个基于字节流的传输服务(UDP 基于报文的),“流” 意味着 TCP 所传输的数据是没有边界的。所以可能会出现两个数据包黏在一起的情况。假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到的字节数是不确定的,故可能存在以下4种情况。
特例:如果此时服务端TCP接收滑窗非常小,而数据包D1和D2比较大,很有可能会发生第五种可能,即服务端分多次才能将D1和D2包接收完全,期间发生多次拆包。
解决
\r\n
标记。FTP 协议正是这么做的。但问题在于如果数据正文中也含有 \r\n
,则会误判为消息的边界。