一、什么是TCP?
TCP是面向连接的、可靠的、基于字节流的传输层通信协议
面向链接:一对一才能链接,不能像UDP协议可以一个主机同时想多个主机发送消息
可靠的:TCP 都可以保证一个报文一定能够到达接收端
字节流:用户消息通过TCP协议传输时,消息可能会被操作系统【分组】成多个的TCP报文,如果接收方当的程序如果不知道【消息的边界】,是无法读出一个有效的用户消息的。并且TCP报文是【有序的】,当【前一个】TCP报文没有收到的时候,即使他收到了后面的TCP报文,也不能扔给应用层去处理,对于【重复】的TCP报文会自动丢弃
二、什么是TCP连接?
用于保证可靠性和流量控制维护的某些状态信息,信息包括:Socket,序列号和窗口大小称为连接。
Socket:由IP地址和端口号组成
序列号:用来解决乱序问题
窗口大小:用来做流量控制
三、UDP和TCP有什么区别?
UDP不提供复杂的控制机制,利用IP提供面向【无连接】的通信服务
UDP的头部只有8个字节
1.连接:
TCP是面向连接的传输层协议,传输数据前先要建立连接
UDP是不需要连接,即可传输数据
2.服务对象:
TCP是一对一的两点服务,即一条连接只有两个端点
UDP支持一对一,一对多,多对多的交互tongxin
3.可靠性:
TCP是可靠交付数据的,数据可以无差错,不丢失、不重复、按序到达
UDP是尽最大交付,不保证可靠交付数据。
4.拥塞控制、流量控制:
TCP有拥塞控制和而流量控制机制,保证数据传输的安全性
UDP则没有,即使网络非常拥堵了,也不会影响UDP的发送速率
5.首部开销:
TCP首部长度较长,会有一定的开销,首部在没有使用【选项】字段时是20个字节,使用了【选项】字段则会变长
UDP首部只有8个字节、并且是固定不变的,开销较小
6.传输方式:
TCP是流式传输,没有边界,但保证顺序和可靠
UDP是一个包一个包的发送,是有边界的,但可能会丢失和乱序
7.分片不同:
TCP的数据大小如果大于MSS大小,则会在传输层进行分片,目标主机收到后,也同样早传输层组装TCP数据包,如果中途丢失了一个分片,只需要传输丢失的这个分片
UDP的数据大小如果大于MTU大小,则会在IP层进行分片,目标主机收到后,在IP层组装完数据,接着再传给传输层
四、TCP连接建立(三次握手)
1.TCP三次握手过程是怎样的?
开始客户端和服务端都处于CLOSE状态。先是服务端主动监听某个端口,处于LISTEN状态
三次握手的第一个报文:SYN报文
客户端会随机初始化序列号(client_isn),此序列号置于TCP首部的【序号】字段中,同时把SYN标志位置为1,表示SYN报文。接着把第一个SYN报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于SYN-SENT状态
三次握手的第二个报文:SYN+ACK报文
服务端收到客户的SYN报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入TCP首部的【序号】字段中,其次把TCP首部的【确认应当号】字段填入client_isn+1,接着把SYN和ACK标志位置为1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于SYN-RCVD状态。
三次握手的第三个报文:ACK报文
客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文TCP首部ACK标志位置为1,其次【确认应答号】字段填入server_isn+1,最后把报文发送给服务端,这次报文可以携带客户到服务端的数据,之后客户端处于ESTABLISHED状态。
服务端收到客户端的应答报文后,也进入ESTABLISHED状态。
第三次握手是可以携带数据的,前两次握手是不可以携带数据的
如何在Linux系统中查看TCP状态?
TCP的连接状态查看,在Linux可以通过netstat -napt命令查看
五、为什么是三次握手?不是两次、四次?
三次握手才可以阻止重复历史连接的初始化(主要原因)
三次握手才可以同步双方的初始化序列号
三次握手才可以避免资源浪费
原因一:避免历史连接
首要原因是为了防止旧的重复连接初始化造成的混乱
两次握手连接为什么无法阻止历史连接呢?
在两次握手的情况下,服务端没有中间状态给客户端来阻止历史连接,导致服务端可能建立一个历史连接,造成资源浪费
原因二:同步双方初始序列号
TCP协议的通信双方,都必须维护一个【序列号】,序列号是可靠传输的一个关键因素,它的作用:
- 接收方可以去除重复的数据
- 接收方可以根据数据包的序列号按序接受
- 可以标识发送出去的数据包中,那些是已经被对方收到的(通过ACK报文中的序列号知道)
原因三:避免资源浪费
如果只有【两次握手】,当客户端发生的SYN报文在网络中阻塞,客户端没有接收到ACK报文,就会重新发送SYN,由于没有 第三次握手,服务端不清楚客户端是否收到了自己回复的ACK报文,所以服务端每收到一个SYN就只能主动建立一个连接,建立多个冗余的无效链接,造成不必要的资源浪费
为什么每次建立TCP连接时,初始化的序列号都要求不一样呢?
如果每次建立连接,客户端和服务端的初始化序列号都是一样的话,很容易出现历史报文被下一个相同四元组的连接接受问题
六、第一次握手丢失了,会发生什么?(超时重传)
当客户端想和服务端建立TCP连接的时候,首先第一个发的就是SYN报文,然后进入到SYN_SENT状态。
若客户端收不到服务端发送的SYN-AVK报文(二次握手),就会触发超时重传机制,重传SYN报文,而且重传的SYN报文的序列号都是一样的。当重传次数超过最大值时,则会再等待一段时间,还是没能收到第二次握手的话,就会断开连接
七、第二次握手丢失了,会发生什么?
当服务端收到客户端的第一次握手之后,就会回SYN-ACK报文给客户端,这个就是第二次握手,此时服务端会进入SYN_RCVD状态
第二次握手的SYN-ACK报文的目的:
- 第二次握手里的ACK,是对第一次握手的确认报文
- 第二次握手里的SYN,是服务器发起建立TCP连接的报文
当第二次报文丢失,客户端可能认为是自己的SYN(第一次握手)报文丢失,于是客户端会触发超时重传机制,重传SYN报文
如果二次握手丢失,服务端收不到第三次握手,于是服务端这边会触发超时重传机制,重传SYN-ACK报文
八、第三次握手丢失了,会发生什么?
客户端收到服务端的SYN-ACK报文后,就会给服务端回一个ACK报文,也就是第三次握手,此时客户端状态进入到ESTABLISH状态
因为第三次握手的ACK是对第二次握手的SYN的确认报文,所以当第三次握手丢失了,如果服务端哪一方收不到确认报文,就会触发超时重传机制,重传SYN-ACK报文(第二次握手)
ACK报文是不会有重传的,当ACK丢失了,就由对方重传对应的报文