介绍TCP/IP协议中每一层里面的核心内容~
提高传输效率的机制
又是基于流量控制,来引入的提高效率的机制
实际TCP
的延时时间,不一定非是用时间来衡量,也可能是用传输轮次来衡量~
比如下图:
每收到两条数据,返回一次ack
是让窗口大点的一种方法~
基于延时应答的基础上,引入的
网络通信中,典型的通信模型,是一发一收
TCP
中,只要把数据传过去,对方收到之后,就会立即由内核返回一个ACK
确认报文
另外,响应数据(fin),则是应用程序里负责传输
ack
返回的时机和fin
(结束报文段)返回的时机是不同的,因此不能把这两次传输合并起来~
但是上面有个延时应答!
本来ACK
是立即就要返回的,但是由于延时应答,稍等一会儿返回~
稍微等一等,正好业务上也要返回这个响应,此时就可以把两个报文合二为一了,可以提高效率~
这个合二为一的操作是内核处理的~ 应用程序是调用socket
的write
方法把数据交给内核,内核进行封装,进行发送~
但是这种情况是偶发的~
主要还是看应用程序什么时候返回响应! 如果应用程序返回的太晚,此时就无法合并~
在面向字节流中,存在一个典型的问题,叫做"粘包问题"
TCP
(或者其他面向字节流的传输方式),都是有一个 接收缓冲区~
A的应用程序,就需要从接收缓冲区中,读取收到的数据~~
由于是面向字节流的,A是无法确定,从哪里到哪里,是一个完整的应用层数据报
A就可能把"吃"当作完整响应
也可能把"吃个"当成完整响应
…
粘包问题:
TCP自身对于应用层数据报是无法做区分的~
UDP面向数据报,是不存在这个问题的~
一个UDP数据报,就是对应一个应用层报文
🥩要想解决粘包问题,就要在应用层协议这里进行区分!
只要定义应用层数据协议的时候,明确包和包之间的"边界",就可以了!!
典型的办法,有两种:
- 通过分隔符 : 比如约定用
;
作为包的结束标记- 通过指定包的长度,比如在数据包开头位置声明长度~
连接异常了怎么办?
- 程序崩溃了
- 正常关机(通过 开始菜单 这种方式来关闭主机)
- 主机掉电
- 网线断开
socket
的 close
close
就会触发 FIN
报文,进一步的开始四次挥手~~ack
了,发送方就触发超时重传,重传几次之后,仍然无应答,发送方就尝试重置连接(复位报文段),也会失败,最后只能放弃连接
TCP
和UDP
之间的对比:
各自的应用场景不同~
传输层也不是只有这两个协议,还有其他的协议~
像平时玩对实时性要求非常好的游戏,一般既需要保证可靠性,又需要保证效率,此时TCP和UDP都难以胜任了~
比如 KCP等…
💌常见面试题:
如何使用 UDP 来实现 可靠传输❔
考察的其实是TCP
说说TCP基于在应用层,来实现确认应答,超时重传,引入序列号等保证可靠传输的机制…