• 【T06】记住TCP是一种流协议


    1、TCP是一种流协议(stream protocol),这意味着数据是以字节流的形式发给接收者的,没有固定的报文和报文边界的概念。
        接收端读取tcp数据,无法预知在这一次读操作中会返回多少个字节。
    2、假设主机A向主机B发送两条报文M1和M2,调用两次send发送两条独立的报文,但是数据在传输过程中并不会遵循这个方式。
        在发送端,send操作只是将数据复制到主机A的TCP/IP协议栈,由TCP决定怎么发送和每次发送多少。
        决定过程很复杂,取决于很多因素。如:发送窗口,拥塞窗口,路径上的最大传输单元等。
        也就是说,主机A真正发送数据的情况有很多种:
        M1和M2分开发送,M1和M2合并起来发送,M1先发送一部分,剩下的和M2一起发送,发送M1和M2的一部分,再发送M2剩下的一部分。
        注意:发送窗口由对端控制,防止发送过多数据,导致接收端的缓冲区溢出。
        拥塞窗口自己控制,tcp要提供可靠的传输服务,因此具备超时重传功能。
        考虑,现在网络比较拥堵,超时没有收到回复,认为丢失,重传。导致越重传,越拥堵,越拥堵,越重传的的恶性循环。
        tcp发送策略的一个主要目标是:尽可能高效地利用网络带宽。因此,对于上述的恶性循环,
        更好的策略是:不要再发送数据了,等到网络缓解的时候在发送。
        拥塞窗口就是,记录当前网络能够容纳的流量。当前tcp能够发送的数据量是发送窗口和拥塞窗口的最小值。
        也就是说,发送窗口允许发送很多数据,但是网络环境比较差,你也必须少发一些。
    3、因此,接收端主机B不能对读取数据做任何假设,需要读几次,每次读多少,都是不可预测的。
    4、对于定长报文来说,接收端读取到一定长度就认为是一个完整报文,那么问题来了,对于不定长的报文,每个报文的长度是不确定的,主机B怎么才能知道读取了一个完整的报文?
    5、解决办法有两个:
        办法一:报文的前面加一个首部,在固定位置标识这个报文的长度,接收端就能知道读取多少,就是一个完整的报文了。
        办法二:在报文中增加结束标记来分割报文,这个结束标记是一个特殊字段。
        那么问题来,如何表示结束标记本身呢? 
        需要使用转义字符。
    
  • 相关阅读:
    java 学习之JVM深入分析(一)
    选择排序算法实现十个1100的随机数的排序
    spring基础知识概述
    mybatis 总结一
    ACM之java判断回文数
    Spring mvc框架
    C#实现窗体最小化到状态栏,双击运行时又能正常显示窗体
    Android调用相机并将照片存储到SD卡上实现方法
    c#中如何让一个窗体在另一个旁边
    C#实现获取时间
  • 原文地址:https://www.cnblogs.com/nzbbody/p/6389593.html
Copyright © 2020-2023  润新知