从字面意思上我们可能会以为Tcp/IP协议就是单纯的TCP、IP协议。然而在很多情况下,它只是利用IP进行通信所必须用到的协议群的统称。
负责数据能够从发送端传输接收端,它向它上面的应用层提供通信服务,属于面向通信部分高层,同时也是用户功能中最低层。
以包裹为例,邮寄员(IP)根据收件人地址(目的IP地址)向目的地(计算机)投递包裹(ip数据报),包裹到达目的地后由对方(传输层协议)根据包裹信息判断最终的接收人(接收端应用程序),如果快递单上只写了地址和名字,而假如该地址有多个同名同姓的人,那么邮寄员就不知道该交给谁,所以现实中我们是不是还通过追加电话号码区分。而TCP/IP通信中也是这样,需要指定类似于电话号码的端口号进行数据传输。
端口号(port)是传输层协议的内容.
描述的是数据是谁发的,要发给谁
用户数据报协议,不提供复杂的控制机制,利用ip提供无连接的通信服务。
发送数据前不需要建立连接,故发送数据结束后也没有连接可释放,因此减少了开销和发送数据之前的时延。
不保证可靠交互,因此主机不需要维持复杂的连接状态表
发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层,UDP对应用层交下来的报文既不合并也不拆分,保留这些报文的边界。也就是说应用层交给UDP多长的报文,UDP就照样发送。(所以要注意选择合适的报文,避免太长IP层进行分片,而太短IP数据报首部相对长度太大,都会降低IP层效率)
网络出现拥塞也不会使源主机的发送速率降低(比如视频会议要求源主机以恒定速率发送数据,并允许在网络拥塞时丢失一些数据,但不允许有太大的时延,UDP正好符合要求)
首部8字节,比TCP20字节的首部短
我们注意到, UDP协议首部中有一个16位的最大长度. 也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部).然而64K在当今的互联网环境下, 是一个非常小的数字.如果我们需要传输的数据超过64K, 就需要在应用层手动的分包, 多次发送, 并在接收端手动拼装。
基于UDP的应用层协议:
NFS: 网络文件系统
TFTP: 简单文件传输协议
DHCP: 动态主机配置协议
BOOTP: 启动协议(用于无盘设备启动)
DNS: 域名解析协议
TCP全称为 “传输控制协议(Transmission Control Protocol”). 人如其名, 要对数据的传输进行一个详细的控制
紧急URG:,紧急指针是否有效。URG=1,表明紧急指针字段有效,告诉系统此时有紧急数据需要尽快传送(相当于由高优先级的数据)
**ACK:**确认号是否有效。仅当ACK=1时确认字段才有效,TCP规定在建立连接后,所有的传送的报文段都必须把ACK置为1。
PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走。有时两个应用程序进行交互式通信时,有一端想键入一个命令立即收到对方的响应,此时TCp可以使用推送(push)操作,发送方TCP把PSH置1,并立刻创建一个报文段发送出去。接收端就尽快接受,不必等到整个缓存填满后再向上交付
RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段.当RST=1代表TCP连接出现严重差错(主机崩溃或其他),必须释放连接然后再重新建立连接。
SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段.当SYN=1,ACK=0,表示这是一个连接请求报文段若对方同意连接则在响应报文段中将SYN=1,ACK=1.因此SYN=1表示这是一个连接请求或连接接受报文
FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段,FIN=1表示数据发送完毕并要求释放传输连接。
生活中两个人对话,是否完全理解对方的说的内容要靠双方的反应。比如听到了就回复嗯,这里的嗯相当于返回了一个确认应答ACK.
比如上图屌丝男和女神的对话,说我爱你时一段时间后女神并没有回复他,说明此时数据已丢失,需要重发。如果没有确认应答,那么屌丝男又给女神发了一条消息,女神这回复了他,那么他就以为女神回复的是第一句,沾沾自喜,哈哈哈哈。
在确认应答机制中我们看到主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据无法到达主机B;如果主机A在一个特定时间间隔内没有收到B发来的确认应答, 就会进行重发。主机A未收到B发来的确认应答, 也可能是因为ACK丢失了因此主机B会收到很多重复数据. 那么TCP协议需要能够识别出那些包是重复的包, 并且把重复的丢弃掉.这时候我们可以利用前面提到的序列号, 就可以很容易做到去重的效果.
如何确定超时重传时间?
时间太长影响整体传输,太短有可能频繁发送重复的包。
所以系统基于TCP协议实现,动态计算报文最大生存时间(MSL),超时时间设置为2MSL
**作用:**超过超时时间表示丢包,需要重新发数据。
注意数据不会被反复,无限重发,达到一定次数强制关闭连接
正常情况下需要3次握手建立连接,4次挥手断开连接。为什么呢,请看下面讲解
LISTEN:收听状态,等待客户建立连接,
SYN-SEND:同步已发送
SYN-RCVD:同步收到
ESTAB-LISHED:已建立连接
上图也就是TCP三次握手(三报文握手):总体来说就是呼叫,应答,回应。一般来说主动发起连接的叫客户,被动等待建立连接的应用进程叫服务器。假设A端运行的是TCP客户程序,B运行的是TCP服务器程序。最初的TCP进程都处于CLOSED状态。
经过这三部后,两台服务器就建立连接了,
为什么需要三次握手呢?
为什么会出现脏连接?因为网络报文生存时间可能会超过TCP请求超时时间,假如两次握手就可以建立连接,传输数据并释放连接后第一个超时连接请求到达B机器的话,B机器以为是A机器创建连接的新请求,然后确认同一创建连接,因为A的状态不是SYI_SEND,所以直接丢弃了B的确认数据,导致只是B单方面建立了连接。并一直等待A发送数据,B的资源也就浪费了。
为什么不是4次或2次握手?
先看下面场景:
两次:,不能。为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误
四次:可以采取4次甚至N次握手,但是有必要吗?建立连接的时间太长,效果也会大打折扣。
如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
先看下面的场景:假如A,B在玩游戏。
A:B啊,我不想玩了
B:好吧,你不想玩了,我知道了。(此时还只是A不想玩了,即A不会再发送数据,但是B能不能直接关闭尼,很有可能是A发完了自己的数据就准备不玩了,而B还没做完自己的事,所以它还具备发数据的能力,此时处于半关闭状态,此时A可以选择不在接收数据或在接受一次数据,等待B也主动关闭)
B:那好吧A,我也不玩了
A:好的拜拜。
第三次数据传输,服务器端发送FIN数据到客户端,客户端处于TIME-WAIT,为什么不能设置为CLOSED?
此时只是单方面的关闭,客户端还要等待服务器发送最后的数据。
为什么TIME-WAIT时间是2MSL?(关于msl头条面试问过:2msl的时间,英文名字,大小是多少?)
MSL(Maximum Segment Lifetime)报文最大生存时间
Windows : MSL = 2 min
linux(Ubuntu, CentOs) : MSL = 60s
Unix : MSL = 30s
返回的是ACK传输时间和服务器重新发送FIN的时间
- MSL是TCP报文的最大生存时间, 因此TIME_WAIT持续存在2MSL的话就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启, 可能会收到来自上一个进程的迟到的数据, 但是这种数据很可能是错误的);
- 同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失, 那么服务器会再重发一个FIN. 这时虽然客户端的进程不在了, 但是TCP连接还在, 仍然可以重发LAST_ACK)如果直到2MSL,客户端都没有再次收到FIN,那么客户端推断ACK已经被成功接收,则结束TCP连接。
为什么4次挥手
确保数据能够完成传输。
但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
能否五次挥手?能否三次挥手?
可以五次挥手,让用户程序再关闭连接前处理需要的任务如释放资源
不能三次挥手,第二次的ACK是系统内核实现的ACK,而FIN是用户手动关闭的。
对于确认应答策略一发一收当数据较长时性能太低, 那么我们一次发送多条数据, 就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了).
那么如果出现了丢包, 如何进行重传?
这种情况下, 部分ACK丢了并不要紧, 因为可以通过后续的ACK进行确认;
- 当某一段报文段丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 "我想要的是 1001"一样;
- 如果发送端主机连续三次收到了同样一个 “1001” 这样的应答, 就会将对应的数据 1001 - 2000 重新发送;
- 这个时候接收端收到了 1001 之后, 再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中;
这种机制被称为 “高速重发控制”(也叫 “快重传”)
接收端通过TCP协议头中”窗口大小“字段,告知发送端发送数据的大小。
目的:接收端能力有限,为了防止接收缓冲区被打满,再接收数据就直接丢弃,接收端主机无法处理。
- 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段, 通过ACK端通知发送端;
虽然TCP有了滑动窗口这个大杀器, 能够高效可靠的发送大量的数据. 但是如果在刚开始阶段就发送大量的数据, 仍然可能引发问题.
因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 贸然发送大量的数据, 是很有可能引起雪上加霜的.
TCP引入慢启动机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据
像上面这样的拥塞窗口增长速度, 是指数级别的. “慢启动” 只是指初使时慢, 但是增长速度非常快.为了不增长的那么快, 因此不能使拥塞窗口单纯的加倍.此处引入一个叫做慢启动的阈值当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长
如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小.
一定要记得, 窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络不拥塞的情况下尽量提高传输效率;
那么所有的包都可以延迟应答么? 肯定也不是;
数量限制: 每隔N个包就应答一次;
时间限制: 超过最大延迟时间就应答一次; 具体的数量和超时时间, 依操作系统不同也有差异; 一般N取2,超时时间取200ms;
在延迟应答的基础上, 我们发现, 很多情况下, 客户端服务器在应用层也是 “一发一收” 的. 意味着客户端给服务器说了"How are you", 服务器也会给客户端回一个 “Fine, thank you”;
那么这个时候ACK就可以搭顺风车, 和服务器回应的 “Fine, thank you” 一起回给客户端
- 首先要明确, 粘包问题中的 “包” , 是指的应用层的数据包.
- 在TCP的协议头中, 没有如同UDP一样的 “报文长度” 这样的字段, 但是有一个序号这样的字段.
- 站在传输层的角度, TCP是一个一个报文过来的. 按照序号排好序放在缓冲区中.
- 站在应用层的角度, 看到的只是一串连续的字节数据.那么应用程序看到了这么一连串的字节数据, 就不知道从哪个部分开始到哪个部分, 是一个完整的应用层数据包.
那么如何避免粘包问题呢? 归根结底就是一句话, 明确两个包之间的边界
- 对于定长的包, 保证每次都按固定大小读取即可; 例如上面的Request结构, 是固定大小的, 那么就从缓冲区从头开始按sizeof(Request)依次读取即可;
- 对于变长的包, 可以在包头的位置, 约定一个包总长度的字段, 从而就知道了包的结束位置;
- 对于变长的包, 还可以在包和包之间使用明确的分隔符(应用层协议, 是程序猿自己来定的, 只要保证分隔符不和正文冲突即可
UDP不存在沾包问题
对于UDP, 如果还没有上层交付数据, UDP的报文长度仍然在. 同时, UDP是一个一个把数据交付给应用层.就有很明确的数据边界.
站在应用层的站在应用层的角度, 使用UDP的时候, 要么收到完整的UDP报文, 要么不收. 不会出现"半个"的情况
- 进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.
- 机器重启: 和进程终止的情况相同.
- 机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行reset. 即使没有写入操作, TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放.
- 另外, 应用层的某些协议, 也有一些这样的检测机制. 例如HTTP长连接中, 也会定期检测对方的状态. 例如QQ, 在QQ断线之后, 也会定期尝试重新连接.
可靠性:
提高性能:
其他:
定时器(超时重传定时器, 保活定时器, TIME_WAIT定时器等
基于TCP应用层协议
HTTP
HTTPS
SSH(安全外壳协议)
Telnet( 远程终端协议)
FTP(文件传输协议)
SMTP(可靠且有效的电子邮件传输的协议)
当然, 也包括你自己写TCP程序时自定义的应用层协议;
○ UDP 是无连接的,即发送数据之前不需要建立连接。
○ UDP 使用尽最大努力交付,即不保证可靠交付,同时也不使用拥塞控制。
○ UDP 是面向报文的。UDP 没有拥塞控制,很适合多媒体通信的要求。
○ UDP 支持一对一、一对多、多对一和多对多的交互通信。
○ UDP 的首部开销小,只有 8 个字节。
○ TCP 是面向连接的运输层协议。
○ 每一条 TCP 连接只能有两个端点(endpoint),每一条 TCP 连接只能是点对点的(一对一)。
○ TCP 提供可靠交付的服务。2017/12/19 OneNote Online
○ TCP 提供全双工通信(允许数据在两个方向上同时传输)。
○ TCP是面向字节流。
○ 首部最低20个字节。
参考TCP的可靠性机制, 在应用层实现类似的逻辑;
例如:
引入序列号, 保证数据顺序;
引入确认应答, 确保对端收到了数据;
引入超时重传, 如果隔一段时间没有应答, 就重发数据