目录
1.传输层的UDP协议
1.职责
2.特点
2.传输层的TCP协议(面试重点)
TCP如何体现可靠性?
TCP做了那些机制来保证可靠性?
1.确认——应答机制:
2.确认段segment
3.超时重传次数是无限的吗?
4.关于超时时间的设置
3.TCP的连接管理
1.三次握手
2.四次挥手
1.三次挥手
2.四次挥手
3.同时挥手
CLOSE_WAIT: 出现在挥手阶段
TIME_WAIT:出现在主动关闭方
4.流量控制——发送量控制
1. 狭义流量控制(Flow Control) 根据对方的接收能力进行控制
2.拥塞控制(Congestion Control)根据网络承载能力进行控制
1.如何知道当前网络承载能力——拥塞窗口
一旦遇到网络拥塞:
在网络层的基础上,实现了进程到进程之间的通信
UDP协议的报头信息:UDP添加的封装(解包、分用)
定长的报头:容易做解包
源端口+目的端口:做分用 | 进程 到进程
校验和:防止数据错误,类似哈希的算法
发送端:hash(有效数据) ->hash1
接收端:hash(有效数据) ->hash2
h1 != h2 : 数据一定出错了,丢弃数据
h1 == h2:大概率认为数据还是源数据
报头:header
有效数据(负荷):payload
不可靠、无连接、面向数据报文
职责:1.进程到进程 2.可靠(承诺的是可靠,不是安全)
选项不是定长的,意味着包头不是定长的
TCP提供了确认应答机制(数据编号机制+超时重传机制),保证了
1.TCP会尽自己最大的努力,将数据发送给对方
2.如果真的遇到发送不过去的情况,TCP至少会告诉发送进程,数据发送失败了
3.保证不会收到错误的数据(通过checksum)
4.TCP能保证收到的顺序一定是有序的(按照发送进程发送时的顺序)
5.TCP会根据对方的接受能力和网络线路的橙子阿能力,进行流量的控制
接收方(对方的TCP)有责任对收到的数据进行确认(ackonwledge)应答
那么如果同时收到多份数据,咋知道应答的是哪份数据呢?
对数据进行编号——序列号(sequence number SN)
32位序号存储本次发送时的数据编号
每个字节占用一个序号
SN:本次发送数据的第一个字节的编号
ASN:希望下次发送的第一个字节的编号 (TCP双方维护各自的序列号SN)
比如: 开始序号从1开始
[abcd] SN = 1
[efgh] SN = 5(刚才的abcd长度是4,接着e就是5)
TCP的一个segment,既可以当发送segment,也可以当确认segment使用。
SN+携带数据payload -> 发送作用
ACK标志位 +ASN ->确认作用
发送:携带数据,填写正确的SN,就是发送segemnt
确认:标志位ACK占一个字节,填1就代表起到了确认作用。需要填写确认序列号ASN(填写下一次期望收到的第一个字节的编号,换言之,ASN之前的数据已经全部收到了)
回到发送端:
当我发送了一份数据,没有收到应答时,可能发生说明?
1.对方没收到
2.对方收到了,并且应答了,但应答没有发送过来
真的遇到没有收到应答:(超时重传机制)
1.不应该无限期的等下去(超时timeout机制)
2.重新发送数据
如下图:主机B收到过2次1-1000,所以主机B需要有去重操作
主机B能否判断出数据有重复? 根据数据中的序号检查
TCP的发送端不用关心超时有没有收到应答的原因是什么,采用统一的超时重传机制即可。
如果接收端真的接受到了重复的数据,直接丢弃即可。
会有一定的上限!
达到上限,发送方(TCP)认为本次线路出现问题了
1.TCP关闭本次连接
2.TCP会通知进程(在java中,采用异常方式IOException)
3.TCP会发送一个resert segment出去
一般这个时间不是一个固定的长度,大多是逐步变长
10s -> 20s -> 40s-> 80s
站在进程角度,像一个有问题的TCP线路中发送数据,多久之后,“我(进程)”如何知道线路有问题
10+20+40+80s之后发现!
作为TCP的发送方,经过一段时间之后,就会发现线路有问题了。
作为TCP的接收方,无法得到线路有问题(无法确认对方是没有数据发送还是发送失败了)
在正式通信之前,需要一个阶段:
1.确认对方在线
2.“同步synchronized”一些基本信息
【建立连接阶段】【正式通信】【断开连接阶段】
拨电话 打电话 挂电话
建立连接阶段:
2和3是会被合并的,俗称TCP的三次握手handshake
segment的种类:发送segment、确认segment、
同步信息(握手阶段使用)segment、挥手segment。如何得知本次segment是哪个?
ACK = 1,代表有确认;SYN = 1,代表有同步;FIN = 1,有挥手
当双方都处于ESTABLISHED状态,说明电话拨通了
1,双方地位完相等,谁都可以通过这条连接发送数据,也都可以通过这条连接接受数据
TCP连接是全双工的。
2.socket.getInput
标志位是FIN,进行断开操作。
主动断开方不一定是主动连接方。
可以合并,但不是必须合并。
一般而言,对于服务器上大量出现的CLOSE_WAIT状态,原因就是服务器咩有正确关闭socket,导致四次挥手没有正确完成。只需要加上对应的CLOSE即可解决问题。
出现在被动关闭方这一层
对方进程要求关闭连接,但我方进程还没有要求关闭连接
进一步判断,检查代码中是否漏写了socket.close()
为啥要有一个状态,不能直接走到CLOSED状态吗?
1.TCP协议内部怎么区分连接的?通过五元组信息
(1)当一个连接关闭后,如果之前释放,则五元组信息可能被再次使用。此时,收到发给这条连接的数据时,不知道数据是给老的还是新的
(2)防止最后一个ACK丢失,对方重新发送
为啥TMIE_WAIT的时间是2MSL(maximum segment live)?
我们如何操作,才能必然永远维护“死链接”?
(1)给读增加一个超时时间(1天)
(2)定期给对方发送消息,保平安(heartbeat 心跳包)
为什么进行发送量控制——减少无用功
1.对方告诉我们接受能力
(TCP缓冲区里装的是:对方接受到&&还没有被应用层读走)
接受能力:TCP的缓冲区(TCP Header.window)还能装多少数据
TCP协议栈每次发送segment,都会携带当前的接收窗口大小。
我们作为发送方,比较实时的知道了对方的接收能力,我们的发送量 <= 接收窗口!
发送方利用滑动窗口的机制,进行发送量的控制。
发送缓冲区:应用层写入,将要发送,但还未发送的数据
注意:此时已发送的数据不能删除,只有确认过的数据才可以删除
注意:此时已发送已确认部分就是可以使用的空间
没有一个精确的值,只能采用一些算法来推出拥塞窗口! 这个算法还在不断发展,我们所 学的是一种比较老的算法
慢开始+快增长
慢开始:一开始,拥塞窗口cwnd很小,cwnd =1
增长阶段:指数阶段+加法阶段 cwnd =cwnd*2
到达阈值之后cwnd+=2
网络拥塞:单位时间里,重传次数超过一定值
1.直接cwnd = 1
2.计算一个新的ssthresh(与之前的网络质量有关)
ssthresh = cwnd /2;
标志位:
URG urgent 晋级的 +16位紧急指针
PSH push :PSH=0,允许TCP把收到的数据暂存一段时间,集齐一定数量再给应用层
UDP:应用层写成功,数据经过网卡已经到达网络,并没有到达对方
UDP:不可靠、无连接、面向数据报
TCP:应用层写成功,数据存到了发送缓冲区,什么时候发送不知道。
TCP:可靠、有连接、面向字节流