传输层

UDP协议(用户数据报协议)

协议格式

传输层_第1张图片

  1. 16位UDP长度, 表示整个数据报(UDP首部+UDP数据)的最大长度;
  2. 如果校验和出错, 就会直接丢弃

协议特点

缺点

  • 无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接;
  • 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息;
  • 面向数据报: 不能够灵活的控制读写数据的次数和数量,对UDP报文整存整取,不拆分不合并。

优点:简单、快速、高效。

缓冲区

  • UDP没有真正意义上的发送缓冲区. 调用sendto会直接交给内核, 由内核将数据传给网络层协议进行后续
    的传输动作;
  • UDP具有接收缓冲区. 但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致; 如果缓冲区满了, 再到达的UDP数据就会被丢弃;
  • UDP的socket既能读, 也能写, 这个概念叫做 全双工

注意

UDP协议首部中有一个16位的最大长度. 也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部).
如果我们需要传输的数据超过64K, 就需要在应用层手动的分包, 多次发送, 并在接收端手动拼装

用UDP实现可靠传输

参考TCP的可靠性机制, 在应用层实现类似的逻辑;

  • 引入序列号, 保证数据顺序;
  • 引入确认应答, 确保对端收到了数据;
  • 引入超时重传, 如果隔一段时间没有应答, 就重发数据;

TCP协议(传输控制协议)

可靠性

连接管理通信
确认应答(ACK)机制

TCP给每个字节的数据都进行编号,称序列号,
每个ACK带有对应的确认序列号,
告诉对方,我收到了哪些数据,下次你从哪里开始发。

按序到达

在上述机制中的序列号来保证的

超时重传

因为网络拥堵等原因,在特定的时间内没有收到对方来的确认应答,就会进行重发。
如何确定超时时间?

  • 设置太长 —> 影响重传效率
  • 设置太短 —> 频繁发送重复包
  • 动态计算最大超时时间
    以500ms为一个单位控制,重发一次得不到ACK,则等待2500ms,仍然得不到ACK,等4500ms,以指数形递增,累积到一定重传次数,TCP认为网络或对方出现异常,强制关闭连接。
流量控制

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

拥塞控制

在不清楚当前网络状态下, 贸然发送大量的数据, 仍然可能引发问题。

  • TCP引入慢启动机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据;
  • 拥塞窗口发送开始的时候, 定义拥塞窗口大小为1;每次收到一个ACK应答, 拥塞窗口加1;每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口;拥塞窗口增长速度, 是指数级别的. “慢启动” 只是指初使时慢, 但是增长速度非常快
  • 引入阈值,约束其加倍情况,当拥塞窗口超过这个阈值, 则按照线性方式增长。

1.当TCP开始启动的时候, 慢启动阈值等于窗口最大值;
2.在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1;

总结:拥塞控制, 是TCP协议想尽可能快的把数据传输给对方, 但是又要避免给网络造成太大压力的折中方案。

提高性能

滑动窗口

确认应答策略, 对每一个发送的数据段, 都要给一个ACK确认应答. 收到ACK后再发送下一个数据段. 这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长。所以我们一次发送多条数据。

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

1、数据包已经到达,ACK被丢失
这种情况下, 部分ACK丢了并不要紧, 因为可以通过后续的ACK进行确认;
2、数据包直接丢了
当某一段报文段丢失之后, 发送端会一直收到要求此段重发的ACK,
如果发送端主机连续三次收到了同样的ACK,就重发
这个时候接收端收到此段之后, 再次返回的ACK就是下段了,因为此段之前接收端已经收到了, 被放到了接收端操作系统内核的接收缓冲区中;
这种机制被称为 “高速重发控制”(也叫 “快重传”)

延迟应答

如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小。

  • 窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络不拥塞的情况下尽量提高传输效率。
  • 数量限制: 每隔N个包就应答一次;时间限制: 超过最大延迟时间就应答一次;
    具体的数量和超时时间, 依操作系统不同也有差异; 一般N取2, 超时时间取200ms;
捎带应答

在确认消息的同时,ACK可携带少量数据。

协议特点

面向字节流
  • 创建一个TCP的socket, 同时在内核中创建一个发送缓冲区和一个 接收缓冲区;既可以读数据, 也可以写数据. 这个概念叫做全双工
  • 由于缓冲区的存在, TCP程序的读和写不需要一一匹配, 例如:
    100个字节数据时, 可以调用一次write写100个字节, 也可以调用100次write, 每次写一个字节;
    100个字节数据时, 也完全不需要考虑写的时候是怎么写的, 既可以一次read100个字节, 也可以一次read一个字节, 重复100次

粘包问题

粘包问题中的 “包” , 是指的应用层的数据包.
在TCP的协议头中, 没有如同UDP一样的 “报文长度” 这样的字段, 站在应用层的角度, 看到的只是一串连续的字节数据,不知那部分到那部分是完整的包。
解决:明确两个包之间的边界

  • 对于定长的包, 保证每次都按固定大小读取即可
  • 对于变长的包, 可以在包头的位置, 约定一个包总长度的字段, 从而就知道了包的结束位置;
  • 对于变长的包, 还可以在包和包之间使用明确的分隔符
    **UDP协议不存在 “粘包问题” **
    对于UDP, 如果还没有上层交付数据, UDP的报文长度仍然在. 同时, UDP是一个一个把数据交付给应用层.就有很明确的数据边界。

基于TCP应用层协议

  • HTTP
  • HTTPS
  • SSH
  • Telnet
  • FTP
  • SMTP

TCP/UDP对比

  • TCP用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景;面向字节流
  • UDP用于对高速传输和实时性要求较高的通信领域, 例如, 早期的QQ, 视频传输等. 另外UDP可以用于广播;面向数据报。

你可能感兴趣的:(JavaWeb)