https://www.bilibili.com/video/BV1Up411Z7hC?p=4&spm_id_from=pageDriver
如有错误之处请指出,谢谢!
目录
p49-p52
TCP
TCP概念
RFCs-793,1122,1323,2018,2581
点对点的通信机制
只能由一个发送方一个接收方
可靠的、按序的字节流
流水线机制
TCP拥塞控制和流量控制机制设置窗口尺寸
介于GBN和SR之间的机制
发送方/接收方缓存
全双工
同一连接中能够传输双向数据流
面向连接
通信双方在发送数据之前必须建立连接
连接状态只在连接的两端中维护,在沿途节点中并不维护状态
TCP连接包括:两台主机上的缓存、连接状态变量、socket等
流量控制机制
TCP段结构
序列号和ack编码是利用数据的字节数来计数
U:URG紧急数据,一般不使用
A:ACK标志位,表示是不是一个有效的ACK
P:PSH,遇到P直接推送到上层,一般不用
R、S、F:RST、SYN、FIN,TCP连接建立与拆除
WIN:接收窗口的大小,所能或者所愿意接受的数量,控制流量
checksum:Internet校验和
序列号:
序列号指的是segment中第一个字节的编号,而不是segment的编号
建立TCP连接时,双方随机选择序列号
防止被攻击者猜到,和与其他冲突,所以设置随机
ACKs
希望接收到的下一个字节的序列号
累计确认:该序列号之前的所有字节均已被正确接收到
Q接收方如何处理乱序到达的Segment?
A:TCP规范中没有规定,由TCP的实现者做出决定
例子telnet远程连接
客户端已经收到了前79个字节的数据,接下来想要收到序号为80的数据
TCP的可靠数据传输
TCP在IP层提供的不可靠服务基础上实现可靠数据传输服务
流水线机制
累计确认
TCP使用单一重传定时器
触发重传的事件
超时
收到重复ACK
渐进式
暂不考虑重复ACK
暂不考虑流量控制
暂不考虑拥塞控制
RTT和超时
问题:如何设置定时器的超时时间
大于RTT:
但是RTT会变化
过短:
不必要的重传
过长:
对段丢失时间反应慢
问题:如何估计RTT
SampleRTT:测量从段发出去到收到ACK的时间:忽略重传
SampleRTT变化:测量多个SampleRTT,求平均值,形成RTT的估计值:EstimatedRTT
定时器超时时间的设置
EstimatedRTT+”安全边界“
EstimatedRTT变化大---->较大的边界
测量RTT的变化值
SampleRTT与EstimatedRTT的差值。加权平均
就是为了防止SampleRTT和estimatedRTT差值过大,影响了(过去稳定数据+偏差较大数据)求平均的结果,采用了比例因子进行加权平均
定时器超时时间的设置
TimeoutInterval=EstimatedRTT+4*DevRTT
TCP发送方事件
从应用层收到数据
创建Segment
序列号是Segment第一个字节的编号
开启计时器
设置超时时间:TimeOutInterval
超时
重传引起超时的Segment
重启定时器
收到ACK
如果确认此前未确认的Segment:
更新SendBase
如果窗口中还有未被确认的分组,重新启动定时器
TCP发送端程序伪代码
例子
TCP接收方事件
1、到达了一个按序的段,这个段之前的所有段都被ACK掉,会等待500ms,如果500ms内没有下一个段则发送ACK(等待防止ACK泛滥)
2、如果按序到达了,且之前有一个段在等待,则立刻发送累计确认ACK
3、有乱序ACK则立刻发送重复ACK
快速重传机制
TCP的实现中,如果发生超时,超时时间间隔将重新设置,即将超时时间间隔加倍导致其很大
重发丢失的分组之前要等待很长时间
通过重复ACK洁厕分组丢失
Sender会背靠背地发送多个分组
如果某个分组丢失,可能会引发多个重复的ACK
如果Sender收到对同一数据的3个ACK,则假定数据之后的段已经丢失
快速重传:在定时器超时之前即进行重传
快速重传的算法
Q为什么是三次?
A因为无法判断是因为乱序还是丢失,乱序更可能重传1到2次,3次及以上更可能是因为丢失
TCP流量控制
接收方未TCP连接分配buffer
上层应用可能处理buffer中数据的速度较慢
flow control
发送方不会传输的太多、太快以至于淹没接收方(buffer溢出)
速度匹配机制
假定TCPreceiver丢弃乱序的segments
Buffer中的可用空间(spare room)
1、receiver通过在Segment的头部字段将RcvWindow告诉Sender
2、Sender限制自己已经发送的但还未收到ACK的数据不超过接收方的空闲RcvWindow尺寸
Q:Receiver告知Sender RcvWindow会怎么样
A:Sender会停止发送,形成死锁
需要TCP中发送方仍可以发送一个很小的段,来带回信息,避免死锁的情况
TCP连接管理
TCP Sender和Receiver在传输数据前需要建立连接
初始化TCP变量:Seq、Buffer和流量控制信息
Client:连接发起者
Socket clientSocket=newSocket("hostname","port number")
Server:等待客户连接请求
Socket connectionSocket = welcomeSocket.accept();
TCP连接的建立:三次握手机制
TCP连接的建立分三个阶段
第一个阶段:客户主机向服务器发送一个SYN报文段
不携带任何数据
携带seq初始序列号(一般为随机)和SYN=1
第二个阶段:如果服务器端同意建立连接,会返回一个SYN&ACK报文段
服务器会分配缓存
同时选择自己的初始序列号seq,和确认ACK
第三个阶段:主机端会答复一个ACK报文段,SYN不在置1,表示受到同意建立连接的报文段
Q:为什么要三次握手,两次行吗
后两次握手是为了保证客户端能接受到服务端的信息并能做出正确的应答
两次握手的话,假如接收方接受到请求后,向发送方发送的包丢失,而发送方以为没有接收到,就一直发送请求,而此时接受方一直在等待数据包
Q会不会在三次握手的第二步服务器就会分配资源?
会分配,会保留一段时间直到确认这个ACK不会再建立了(SYN泛洪攻击,ddos)
TCP连接的拆除:四次挥手
客户机和服务器都可以发起
//client closes scoket:clientSocket.close();
第一步
客户机向服务器发送TCP FIN控制报文段
第二步
服务器收到FIN,会回复一个ACK报文段,关闭连接,并发送一个FIN控制报文段
第三步
客户机收到FIN,会回复一个ACK报文段
进入等待状态--如果重复收到FIN,会重新发送ACK
第四步
服务器收到ACK,连接关闭