前言
在工作中,每周都会遇到一些问题,这些问题在大家工作中可能会有许多共性,于我也是一种经验的积累小结。我觉得花一些时间整理一下,跟粉丝读者们分享一下日常工作遇到的问题,这是一个很好的互动和文章分享的痛点。
这是第十一篇。
TCP知识小结
闲来没事,又逢看了一篇TCP协议的微信文章,讲的很不错的,从头到尾看了一遍,这周的文章就是来用自己的语言重述一下。
TCP头格式
TCP的报文头憨憨端口号、序列号、应答序列号、首部长度、状态标志位、窗口大小、校验和、紧急指针、选项,之后紧跟着数据。
端口号就是用于标识TCP连接的。
序列号就是用于保证网络包时序的,客户端和服务端在建立连接的时候,分别初始化一个序列号,后续序列号递增。
应答序列号表示期望收到的下一个包的序列号。
状态标志位: ACK表示应答序列号有效。除了首个SYN包外,其他包基本上都是置1的。RST 表示需要中断连接。SYN表示希望建立连接,同时序列号字段表示初始包序号。FIN表示结束连接,后续不再有新数据了。
TCP的用途、TCP和UDP区别
由于IP层是不可靠的,不保证网络包的按序交互及完整性。TCP是一个工作在传输层的可靠的数据传输服务,确保网络包的按序完整接收。TCP是一个面向连接的、可靠的、基于字节流的通信协议。TCP需要维护连接的状态信息,用于保证可靠新和流量控制。
UDP提供无连接的服务,不保证网络包的交付及时序。UDP是以包为单位的。TCP是一对一的连接,UDP支持一对多、一对一、多对多的交互通信。TCP有流量控制,保证数据传输的安全性,UDP则没有,UDP的发送速率不会自适应变化。TCP的首部比较长,可以带有选项,长度>=20。UDP的头部长度固定为8个字节。TCP的分片在TCP层处理,UDP的分配在IP层处理。TCP一般用于安全性要求的FTP、HTTPS等应用。UDP用于包总量少的DNS、SNMP,音视频、广播通信。
TCP有首部长度字段,是由于TCP头部可以包含选项,而UDP头部是固定的。UDP含有一个包长度字段,这个字段当然可以从IP长度计算而来,主要还是为了让首部长度为4的倍数。
TCP连接建立
连接的建立需要一个三次握手的过程,最开始客户端与服务端都是CLOSED状态,首先服务端先进入LISTEN状态,客户端发送SYN包,自身处于SYN-SENT状态; 然后服务端收到报文后,如果自身是LISTEN状态则发送SYN/ACK包,服务端切换到SYN_RECV状态;最后客户端收到了SYN/ACk状态,发送一个ACK包(这个包可以有数据内容),状态切换到ESTABLISHED,服务端收到ACK包后也进入ESTABLISHED。
只有经过三次握手,才可以阻止历史重复连接的初始化,同步双方的序列号、避免资源浪费(不需要4次)。如果在连续发送多个SYN包的时候,服务端在收到旧包的时候,发挥的SYN/ACK包中的应答序列号比较小。客户端收到后,判断这是一个旧的连接,发送一个RST给服务端,中断旧的连接。同步序列号需要双方都确定对方知道自己的序列号,至少需要三次报文。
初始序列号是根据一个基于时钟的M值+连接的四元组哈希值。
TCP分片不放在IP层做的主要原因是IP层没有超时重传的机制,不保证包的交付。所以TCP在发送数据超过协商的MSS时,就主动分包了。
SYN攻击就是不断地发送伪装的IP的SYN报文给服务端,导致服务端处理不过来,无法正常服务。解决方案一,可以修改SYN队列的长度、设置SYN_RECV状态连接数,超过连接数后发送RST。解决方案二,就是服务端在SYN队列满的时候,返回SYN_ACK包序列号为一个cookie值,再等收到ACK后校验序列号来确认是否是真的客户端。伪装的客户端是收不到这个SYN_ACK包的,因为他的IP不是伪装的IP,只要真正的客户端才会应答ACK。
TCP连接断开
断开是一个四次挥手的过程。客户端发送一个FIN报文,状态变为FIN_WAIT_1, 服务端收到了FIN报文后,应答ACK,状态变更为CLOSE_WAIT。客户端收到ACK后,状态切换为FIN_WAIT_2。服务端发送一个FIN报文,状态切到LAST_ACK,等待客户端发送ACK。客户端收到FIN报文,应答一个ACK,状态切为TIME_WAIT,等待2MSL后 关闭。服务端收到ACK后切为CLOSE。在Linux中MSL默认为30s,所以TIME_WAIT状态至少是1min。
TCP保活机制
如果连接一段时间内没有活动,TCP讲主动发送探测报文,间隔一定时间发送一个,超过几次没有收到回应则认为该连接已经断开,关闭连接。
1 | Keep:~ keep$ sysctl -a | grep keep |
可以看到,默认2小时没有活动启动保活机制。间隔75s发送一个探测包,超过8个报文没有应答则断开连接。默认系统最少需要两个小时11分钟才发现连接断开了。
中间如果有收到正常应答,则TCP保活时间重置为两小时。如果收到了RST则连接会被重置。
更多
回顾了一下TCP的连接与断开、保活机制、TCP和UDP的区别。
这些东西都是协议的定义,了解了这些实现可以在实际工作中借鉴来解决问题。协议都是一些死的东西,但是深入研究一下的话,可以发现其中的奥秘。也可以对相关问题的解决定位提供认知。学习最大的乐趣就是可以学以致用。
行动,才不会被动!
欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。