传输层协议

TCP

TCP特点

  • 有连接, 可靠, 面向字节流

TCP报文

  • 源/目的端口号: 表示数据是从哪个进程来,到哪个进程去;
  • 32位序号/32位确认号
  • 4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节); 所以TCP头部最大长度是15 * 4 = 60
  • 6位标志位:
    • URG: 紧急指针是否有效
    • ACK: 确认号是否有效
    • PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
    • RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段
    • SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段
    • FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段
  • 16位窗口大小: 提高传输效率
  • 16位校验和: 发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含TCP首部, 也包含TCP数据部分.
  • 16位紧急指针: 标识哪部分数据是紧急数据;
  • 40字节头部选项

TCP的"可靠"

序号与确认序号

  • TCP将每个字节的数据都进行了编号. 即为序列号 : 保证了数据有序 + 去重
  • 每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发.

超时重传
  • 如果主机A在一个特定时间间隔内没有收到B发来的确认应答, 就会进行重发 

快重传
  • 如果发送端主机连续三次收到了同样一个确认应答, 发送端会将对应数据重新发送

滑动窗口
  • (提高传输效率)

  • 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值. 上图的窗口大小就是4000个字节(四个段). (一次可以发送多个数据)
  • 发送前四个段的时候, 不需要等待任何ACK, 直接发送;
  • 收到第一个ACK后, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推;
  • 操作系统内核为了维护这个滑动窗口, 需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉;
  • 窗口越大, 则网络的吞吐率就越高;

流量控制
  • (解决收发速度不匹配)

接收端处理数据的速度是有限的, TCP支持根据接收端的处理能力来决定发送端的速度

发快, 接收端缓冲区满, 在来的数据接收不了(导致丢包), 导致重传等一系列连锁反应

  • 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 "窗口大小" 字段, 通过ACK端通知发送端;
  • 窗口大小字段越大, 说明网络的吞吐量越高;
  • 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端;
  • 发送端接受到这个窗口之后, 就会减慢自己的发送速度;
  • 如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端

拥塞控制(缓解网络拥塞)

网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 若还发送大量的数据,是很有可能造成更加拥堵

少量的丢包, 我们仅仅是触发超时重传;  大量的丢包, 我们就认为网络拥塞;

TCP引入慢启动 机制,先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数

  • 此处引入一个概念程为拥塞窗口
  • 发送开始的时候, 定义拥塞窗口大小为1;
  • 每次收到一个ACK应答, 拥塞窗口加1;
  • 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口;

  • 1.开始: 拥塞窗口设为1, 每收到1个ACK, 拥塞窗口大小+1 --> 呈指数型增长
  • 2.达到慢阈值变为线性增长
  • 3.又造成网络拥塞
    • 1.重新进行拥塞控制
      • 慢阈值减半 + 拥塞窗口变为1
    • 2.快速恢复(收到3个重复的ACK)
      • 慢阈值减半 + 线性增长

TCP的"效率"

延迟应答
  • (等待上层读走速度留够空间)
  • 假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K;
  • 但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了;
  • 在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;
  • 如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M

捎带应答

发数据的时候捎带ACK

连接管理机制

  • 三次握手
    • 第一次握手:客户端发送一个SYN(同步序列编号)报文给服务器,并进入SYN_SEND状态,等待服务器确认
    • 第二次握手:服务器收到SYN报文后,必须确认客户端的SYN (ACK),同时自己也发送一个SYN报文,即SYN+ACK报文,此时服务器进入SYN_RECV状态
    • 第三次握手:客户端收到服务器的SYN+ACK报文后,向服务器发送确认报文ACK,此报文发送完毕后,客户端和服务器都进入ESTABLISHED状态,完成三次握手

  • 四次挥手
    • 一般客户端是主动关闭端, 服务端是被动关闭端
    • 第一次挥手:  客户端处理完数据向服务端发送FIN包, 然后进入FIN_WAIT1状态
    • 第二次挥手:  服务端收到FIN包, 给客户端发送ACK, 服务端进入CLOSE_WAIT状态去处理剩下的数据, 客户端收到ACK进入FIN_WAIT2状态
    • 第三次挥手:  服务端处理完数据, 给客户端发送LAST_ACK,  
    • 第四次挥手:   客户端收到ACK, 给服务端发送ACK之后进入TIME_WAIT状态(等待2MSL)之后关闭连接

TIME_WAIT状态

  • 规定:主动断开连接的一方,要处于TIME_WAIT, 等待两个MSL时间后,才能回到CLOSED
  • MSL:是TCP报文的最大生存时间
  • 等待两个MSL时间:
    • 保证最后一个报文可靠到达. 
    • 保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失

CLOSE_WAIT状态

  • 设A方已经完成数据的传输,发送断开连接请求. 而B方还没有完成数据的传输就会进入该状态
  • 若有大量的CLOSE_WAIT状态可能说明连接没有正确关闭

粘包问题

引发

  • 发送大量小数据包: 小数据包在传输过程中被合并成一个大的TCP数据报
  • 接收方来接收不及时: 接收方接收不及时, 数据包在缓冲区可能会被合并成一个大数据块

解决: 明确包之间的界限

  • 对于定长的包, 保证每次都按固定大小读取即可
  • 对于变长的包, 可以在包头的位置, 约定一个包总长度的字段
  • 对于变长的包, 还可以在包和包之间使用明确的分隔符(协议)

TCP异常

  • 进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.
  • 机器重启: 和进程终止的情况相同.
  • 机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行reset.  即使没有写入操作, TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放

UDP

  • 无连接状态: 知道对端的IP和端口号就直接进行传输, 不需要建立连接
  • 不可靠:  没有确认机制, 没有重传机制. 出错不会管
  • 面向数据包: 不能够灵活的控制读写数据的次数和数量 
  • 发送速度快: 立即发送

UDP报文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值