服务

  • 端口号,用于指向某个进程,IP地址+端口号 指向网络中的一台主机上的一个特定进程

  • 主机之间的端口号是相互独立的,TCP、UDP的端口号也是相互独立的

  • 进程通信需要:

    • 那种传输层协议
    • 绑定的端口号
    • 对方的IP地址和端口号
  • 熟知端口号:

    • 0~1023 用于重要程序
    • 登记:1024~49661(服务器)
    • 短暂端口号(客户端)
  • 复用和分用

    • 多个端口可以复用TCP协议
    • 数据分派一个协议分给多个进程(分用)
  • 差错检测

    • TCP 面向连接(有连接步骤,先建立连接),可靠的
    • UDP 不面向连接,不可靠,实时性

UDP

  • 首部很小 8B
  • 每次传输一个报文,不支持拆分重状
  • UDP不支持拥塞控制
  • UDP支持一对一,一对多

结构如上,UDP长度不能超过IP数据报长度,所以其实应该是最长 65515B

UDP检验

32bit数据,分成两个16bit相加,结果逐位取反得到校验和

接收方将三组数相加,得到全1,则说明没有错误,否则有错误

这种模式可用于更多数据的校验,例如48bit等等,分成多个16bit相加,如果进位到17位,则循环进位,给第一位进位

UDP的校验用同样的算法(包含首部和数据),形式如下:

要注意计算之后去掉伪首部,将校验和填入首部

对接收方

伪首部的构造一致

TCP

  • 首部大,20~60B(这与IP首部一致)
  • 支持报文自动拆分,重装,传输长报文
  • 有链接的,可靠的,支持拥塞控制
  • TCP支持一对一传输(不支持一对多)

基础

三次握手,四次挥手:

三次握手构建关系,两次挥手单方面断开

TCP是面向字节流的(UDP面向报文),不管有多少报文,每个报文多长,每次按照约定好的 MSS(Maximum Segment Size) 将数据分成合适长度的TCP段并发送

主要解决三个问题

  • 确知对方存在
  • 协商一些参数
  • 对运输实体资源进行分配和初始化

TCP格式

  • 端口号 0~65535 (16bit)

  • 序号 (32b) 就是偏移量,标记这个数据的起始部分在原始字节流中的位置

  • 确认号(ack,ack_seq) ,含义是在这个确认号之前的所有数据都正确接收(累计确认

  • ACK 标志之一,表示确认号是否有效(**只有握手1中无效,其他握手都有效

  • 数据偏移(TCP报文中首部的长度),4B为单位,共4bit,最长就是 15*4 = 60 为了筹够4B整数倍,TCP最后加了一个填充

  • 其他标志位:URG(紧急数据),有效值时紧急指针有效,标记紧急数据的序号(这个序号是 独立的 )

  • PSH 表示希望接收方尽快回复(交互式通信)

  • RST,非整圆的几个

  • SYN(链接接受),同步位

    • 只有握手1,2中SYN为1
  • FIN表示的是终止位,为1时表明数据方的数据已发送完毕,要求释放传输连接

    • (在释放连接的4次挥手中)只有挥手1,3中是1,其他的为0
    • 第一次握手是告知数据已传输完
  • 窗口:表示接收窗口,从ack_seq中 算起,还可以接收多少数据,实现流量控制关键,

  • 校验和(与UDP一致)

  • 选项(长度可变),在握手1,2之前先协商MSS(最大段长)

三次握手关键点:

  • 握手1,2没有携带数据,但是要消耗一个序号(也就是ack +1)
  • 握手3可以不携带数据,此时不用多占用一个序号

四次挥手

四次挥手是释放连接的方式,彼此先通知要释放连接,再各自响应

注意到:

  • FIN在挥手的1,3中
  • 就算不带数据,挥手1,3也要消耗一个序号
  • 挥手2可以带数据,4不可以(因为2是服务器发送的,发送的时候服务器对客户的数据传输还没关闭,相反4是客户的,在挥手4时,其信息

另有状态转换图:

MSL(最长报文段寿命) ,在TIME-WAIT阶段的等待时间(其实是2MSL),目的是避免对方接收不到自己发送挥的手4,所以等待一段时间再退出

当考虑时间时,要考虑的是RTT(通信往返时间)和MSL

Note

为什么要有三报文握手

如果没有最后的一个确认,就没有提醒TCP服务器连接是否成功建立,如果实际上没有成功建立,那么发送的数据就无法送达,但服务器并不知道

TCP流量控制

流量控制方法

  • 通过对TCP发送(接收)的窗口的大小进行限制来控制流量
  • 在累计确认中接收端给发送端明确了接收窗口大小,来限制发送端的发送窗口大小(TCP发送方的发送窗口值=min(TCP发送方的拥塞窗口值,TCP接收方的接收窗口值))
  • 在多次累计确认时给出多次流量控制,最后一次设置窗口为0窗口,停止发送

在下一次开始传输时会发送给一个非零窗口通知,开启下次传输,但如果此时这个通知丢失,双方会互等,形成死锁

所以设计了一个超时重传的机制,当接收导零窗口通知时,会启动计时器,时间到了就发送零窗口测探文段(1字节),在对方确认这个测探报文段时,给出自己现在的窗口值,如果不是0,则死锁可以被解除。

TCP拥塞控制

网络中某一资源的需求超过了该资源所能提供的可用部分,网络性能变坏,称为拥塞,如果出现拥塞而不做控制,则吞吐量将随输入负荷的增大而下降

流量控制与拥塞控制区别

流量控制是控制发送速率,确保不会持续以超过接收方接收能力的速率发送数据

拥塞控制是防止过多数据注入到网络中,使网络能够承受现有的网络负荷

分为如下两种控制方法:

闭环使用较多,下面只讨论闭环

闭环往下分为:

  • 显示反馈算法
    • 拥塞节点向源点提供拥塞状态的显式反馈信息
  • 隐式反馈算法
    • 源点自身通过网络行为的观察(超时重传,RTT等)来判断网络是否发生了拥塞。(TCP)

拥塞算法缺点是:

  • 可能需要在节点之间交换信息和各种命令,以便选择拥塞控制的策略并实施控制,这样会产生额外开销。
  • 可能需要预留一些资源用于特殊用户或特殊情况,这样就降低了网络资源的共享程度。

主要方法

不考虑拥塞控制的情况下,swnd = rwnd

慢开始和拥塞避免

  • 设置一个阈值 ssthresh,如果拥塞窗口小于门限,就采用慢开始算法,如果大于门限,则改用拥塞避免算法
  • 小于门限,每次乘以2 ,超过门限,每次加一(拥塞避免算法),线性变化
  • 如果出错,重置为0,采用慢开始,同时门限变为拥塞时的二分之一

快重传和快恢复

  • 可能会有包丢失然后误认为是拥塞的情况发生
  • 快重传就是 发送方尽快重传,而不是等待超时重传,
  • 其方法是接收到一个报文段之后发送确认报文,如果没有接收到,中间某个丢失,会发送重复确认报文段,超过三次的话,发送方会重传该报文段
  • 发送方将慢开始的门限值和拥塞窗口值调整和当前的拥塞窗口的一半,并开始执行拥塞避免算法

另外有一个TCP拥塞控制和网际层拥塞控制的关系

完整例子

TCP可靠传输实现

Warning

ack在不同协议的含义

在选择重传协议中,其含义是到序号为n为止的数据已正确接收,现在期望收到序号为n+1的数据

在TCP中,表示n-1的数据正确接收,希望收到序号为n的数据

TCP传输以字节为单位,发送有缓存设置,在窗口移动之前,窗口内部的值都在缓存之中,在超时重传时发挥作用

如果接收窗口缩小了,那么发送窗口也应该缩小,后沿不动(已发送一端),前沿缩小(未发送一端)

一些注意点:

  • 同一时刻发送窗口并不总是和接收窗口一样大(有滞后),也可能拥塞之后缩小自己的尺寸

超时重传时间RTO

略大于加权平均往返时间RTTs(否则可能还没到就重传,或者空闲时间太多),计算较为复杂

但实际上RTT时间也很难统计,可能难以判定确认信号是超时重传的确认,还是原本的确认

Karn算法 提出只统计无重传的RTTs,但是依旧存在,如果时延突然增大很多,那么在原本的RTO时间内会导致重传,但是重传的RTTs不计入RTO的更新,也就是说RTO不会更新,那每次都要重传,这明显不妥

可能出现的题目:

TCP选择确认

保证只重传未确认的内容

在首部中的选项部分设置接收到的字节块的边界,来选中已确认的字节