TCP/UDP
TCP/UDP
感觉学的还是不够深吧,很多东西都是流于表面(被字节跳动二面整惨了)。
TCP
源端口号(16位),目标端口号(16位)
序列号(32位)
确认应答号(32位)
首部长度(4位)保留(6位)标志比特位(6个1位的)窗口大小(16位)
校验和(16位)紧急指针(16位)
序列号:
在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。
确认应答号:
下一次期望收到的序列号,发送端收到之后可以确认正常接收。解决不丢包问题。
标识位:
标识 | 用途 |
---|---|
URG | 紧急指针(u rgent pointer)有效。 |
ACK | 确认序号有效。TCP规定除了最初建立连接的时候这个位置必须为1. |
PSH | 接收方应该尽快将这个报文段交给应用层。 |
RST | 连接异常,断开连接 |
SYN | 同步序号用来发起一个连接。 |
FIN | 断开连接 |
关于连接:
用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括Socket、序列号和窗口大小称为连接。
- Socket:由 IP 地址和端口号组成
- 序列号:用来解决乱序问题等
- 窗口大小:用来做流量控制
TCP/UDP
UDP首部:
源端口号(16位),目标端口号(16位)
包长度(16位),校验和(16位)
TCP 和 UDP 应用场景:
由于 TCP 是面向连接,能保证数据的可靠性交付,因此经常用于:
FTP 文件传输、HTTP / HTTPS
由于 UDP 面向无连接,它可以随时发送数据,再加上UDP本身的处理既简单又高效,因此经常用于:
DNS 、SNMP、视频、音频等多媒体通信、广播通信
TCP和UDP的区别
- 连接
TCP 是面向连接的传输层协议,传输数据前先要建立连接。
UDP 面向无连接,即刻传输数据。 - 服务对象
TCP 是一对一的两点服务,即一条连接只有两个端点。
UDP 支持一对一、一对多、多对多的交互通信 - 可靠性
TCP 是可靠交付数据的,数据可以无差错、不丢失、不重复、按需到达。
UDP 是尽最大努力交付,不保证可靠交付数据。 - 拥塞控制、流量控制
TCP 有拥塞控制和流量控制机制,保证数据传输的安全性。
UDP 则没有,即使网络非常拥堵了,也不会影响 UDP 的发送速率 - 首部开销
TCP 首部长度较长,会有一定的开销,首部在没有使用「选项」字段时是 20 个字节,如果使用了「选项」字段则会变长的。
UDP 首部只有 8 个字节,并且是固定不变的,开销较小。
三次握手
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
为什么不是二次握手?
-
可以避免历史连接:
假如旧的SYN包比新的SYN包更早到达服务端。
那么此时服务端返回SYN+ACK包给客户端。
客户端发送RST报文给服务端,表示中止连接。 -
同步双方初始序列号
序列号可以是接受方去除重复的数据,更具数据包的序列号按序接收,可以标识发送出去的数据包中,哪些是已经被对方收到的。 -
避免资源浪费
在两次握手的前提下,客户端的SYN请求连接在网络中阻塞,客户端没有收到ACK报文,就会重新发送SYN,由于没有三次握手,服务器不清楚客户端是否接收了自己发送的ACK确认信号,所以每收到一个SYN就只能先主动建立一个连接。
SYN攻击
伪造不同的IP地址来向服务端发送SYN报文,但服务端发出的ACK+SYN报文无法得到伪造IP地址的回应,于是就会占满SYN接收队列。
避免方式:
- 让队列大小和队列满的时候做一系列处理。
- 当SYN队列满之后,后续的SYN包不进入队列,计算一个cookie值,然后SYN+ACK包返回客户端,服务端接收到客户端的应答报文时,检查ACK合法性。如果合法,直接放入到「 Accept 队列」。
最后应用通过调用 accpet() socket 接口,从「 Accept 队列」取出的连接。
四次挥手
对于一个已经建立的连接,TCP使用改进的四次挥手来释放连接(使用一个带有FIN附加标记的报文段)。TCP关闭连接的步骤如下:
第一步,当主机A的应用程序通知TCP数据已经发送完毕时,TCP向主机B发送一个带有FIN附加标记的报文段(FIN表示英文finish)。
第二步,主机B收到这个FIN报文段之后,并不立即用FIN报文段回复主机A,而是先向主机A发送一个确认序号ACK,同时通知自己相应的应用程序:对方要求关闭连接(先发送ACK的目的是为了防止在这段时间内,对方重传FIN报文段)。
第三步,主机B的应用程序告诉TCP:我要彻底的关闭连接,TCP向主机A送一个FIN报文段。
第四步,主机A收到这个FIN报文段后,向主机B发送一个ACK表示连接彻底释放。
为什么是四次挥手?
相较于三次握手来说,多了第三次挥手,客户端发送了FIN包之后仅仅表示客户端不会发送数据了,但是还是能接收数据。
这个时候服务端也有可能发送信息到客户端。