SYN泛洪攻击、可靠传输(两个机制、一个校验和)、面向连接(五个机制)、面向字节流、粘包
握手失败后服务端如何处理:若服务端回复ACK+SYN后,迟迟无法得到恢复,则服务端会发送RST重置连接报文。然后销毁socket。
SYN泛洪攻击:
恶意主机,不断的发送SYN请求给服务器,但是不进行最后一次ACK回复。
TIME_WAIT状态有什么用:保护主动关闭方,避免立即使用相同地址信息通信。保护客户端,服务端就算重启,也必须使用与以前相同的地址信息(没有TIME_WAIT最好,否则重启还需要等待一段时间)
假如没有这个TIME_WAIT状态,主动关闭方直接释放socket,意味着端口和地址可以立即重新使用。
若最后一次主动关闭方发送ACK丢失。被动关闭方等待最后一个ACK超时后就会重传FIN包。
假如主动关闭方主机立即使用了刚才套接字的端口和地址信息重新启动程序。
- 1.新的程序使用原先的地址信息进行通信,有可能会收到对方重传的FIN包,可能会对新连接造成影响。
- 2.假设新的程序使用原先的地址信息连接相同的服务器。而这个时候服务器有可能在等待最后一次ACK。
这些都属于上一次的连接没有完全清理完毕,导致对新的连接造成影响。因此主动关闭方必须等待一段时间,2个MSL-2个报文的最大生存周期,能够处理被动关闭方有可能重传的FIN包。并且等待本次通信的所有数据都消失在网络中。避免对后续连接造成影响。
TIME_WAIT是主动关闭方才有的状态,常出现于爬虫服务器,大量的主动关闭连接。
可靠传输:
可靠传输:保证数据能够安全有序到达对端(只要不是网络断开一定保证数据到达对端)
- 确认应答机制:对于发送的每一条数据,都要求接收方进行确认回复
- 超时重传机制:在指定时间内没有收到确认回复,这认为数据丢失,对之前的数据进行重传
协议字段中的序号/确认序号:进行包序管理,并且实现确认应答机制
确认序号,功能就是告诉发送方,这个确认序号以前的数据都已经收到了
如果第一条数据丢失,就算收到第二条,也不会进行回复。因为每一条回复表示的都是前边的数据都已经完全收到了。
这种方式可以避免因为ack确认恢复的丢失而导致的重传。
对发送方来说,收到1025,表示1-1024成功传输。收到2049,表示1-2048成功传输。
校验和
协议字段中的校验和:校验数据是否一致,不一致则要求对方进行重传。
哪一条数据不一致,则回复这条数据的起始序号。
比如1-1024的数据不一致,则会回复确认序号1,要求对方重传1起始的数据。
面向连接
面向连接:保证连接建立成功之后在发送数据。
-
滑动窗口机制:通过协议字段中的窗口大小实现-通过窗口大小告诉对方最多发送多少数据,避免因为发送数据过多,接收缓冲区满溢导致的丢包。
在三次握手的时候,通信双方会通过选项数据协商一个信息:MSS-最大数据段大小(应用层的原始数据大小)
tcp发送数据的时候,会从发送缓冲区中取出不大于MSS大小的数据封装tcp头部进行发送
窗口大小通常不大于接受方,接收缓冲区中剩余空间大小 -
快速重传机制:
发送方连续发送多条数据时,若接受方首先收到了第二条数据,则有理由认为第一条数据有可能丢失,因此开始向发送端连续发送三条第一条数据的重传请求。
发送方接收到连续三次重传请求,则会对这条数据进行重传。
三次:有可能前边的数据只是延迟了,而并非丢失了。三次重传请求之间就可以有一个缓冲时间,这个时间内若受到了第一条数据,三次重传请求没有发送完,则发送端就可以不用重传了。
重传这里存在三种协议:停等协议/选择重传协议/回退n步协议- 停等协议:收到一条回复才会发送第二条数据–适用于网络状况特别差的场景
- 选择重传协议:哪条丢失了,就重传哪条
- 回退n步协议:从丢失的数据开始,往后的数据都需要重传一遍
-
拥塞机制:活动窗口实现一次连续发送多条数据,一开始在网络状况不明的情况下,有可能会造成因为网络速度不好而导致发得越多,丢得越多。因此应该在发送数据时,进行网络探测,查看网络是否能够支持数据的连续快速传递
实现原理:慢启动,快增长。通过拥塞窗口实现。 -
延迟应答机制:
因为接受方若接收到数据之后立即回复,则窗口大小会变小,传输吞吐量就会降低。
因此接受方使用延迟应答机制,延迟一段时间再进行确认回复。因为在延迟的这段时间内,有可能数据就会被用户取出,保证传输吞吐率。 -
捎带应答机制:
因为每一条确认回复,都是一个确认回复序号。但是为了确认回复,必须组织一个tcp数据包发送给对端,会造成大量空包的发送。
多接受方即将发送一条数据给对端,则可以在这条即将发送的数据包投不中对上一条数据进行确认回复,节省一个空报头的传输。
可靠传输:
可靠传输的实现:面向连接/确认应答机制/超时重传机制/序号/确认序号/校验和
避免丢包:滑动窗口机制/拥塞机制
提高性能:快速重传机制/延迟应答机制/捎带应答机制
面向字节流:
提供的是可靠的、有序的、基于连接的字节流传输。
字节流传输:数据可以在缓冲区中进行堆积,取出比较灵活,以字节为单位进行取出/存放,传输比较灵活。
发送缓冲区中有很多数据,tcp就会根据mss取出合适大小的数据进行传输。
接收缓冲区中有很多数据,tcp也可以灵活的以用户需要大大小向上交付。
但是这种数据在缓冲区中堆积有一个缺陷–tcp粘包,将多条数据当作一条进行处理。
tcp粘包
- 粘包的本质原因:tcp在传输层对数据边界不敏感(不管上层数据是什么样的,每次都根据mss取出合适大小进行发送/不管接收缓冲区中是什么数据,只管从缓冲区中取出用户需要大小的数据进行交付),因此造成了粘包问题。
- 粘包的解决方案:程序员在应用层进行数据的边界管理。
1.特殊字符间隔 — 每条数据结尾有个特殊字符。数据中包含的特殊字符就需要进行转义了。
2.数据定长 — 每次只发送/接受指定长度的数据。数据过短造成资源浪费。
3.在定长的应用头中定义数据长度字段 — 先按照指定长度将头部获取,根据头部中的长度,取出指定长度数据。
比较典型的:http 先用特殊字符间隔头部,头部中定义正文长度。
udp 头部定长,在头部中定义数据长度。
udp不会产生粘包!!!udp数据是整条收发的。
udp如何实现可靠传输?其实问的是tcp是如何实现可靠传输的。因为把tcp实现可靠传输的机制拿到应用层给udp就可在实现udp可靠传输。