TCP网络协议概述
TCP 是一个可靠的(reliable)、面向连接的(connection-oriented)、基于字节流(byte-stream)、全双工(full-duplex)的协议。
专有名词
MTU:最大传输单元,一般为1500
MSS:最大段大小, MSS = MTU - 20(IP头大小)- 20(TCP头大小)= 1500 - 20 -20 = 1460
MSL:报文最大生存时间,一般为30秒
网络分层
-
应用层
对应协议有 HTTP,DNS,SMTP,FTP等
-
传输层
对应协议有TCP,UDP
-
网络互联层
IP 协议
-
网络访问层
网络访问层也有说法叫做网络接口层,以太网、Wifi、蓝牙工作在这一层,网络访问层提供了主机连接到物理网络需要的硬件和相关的协议,对应协议:Ethernet。
TCP连接建立(三次握手)
-
第一次握手:客户端发送一个 SYN 报文段。
该报文不携带数据,但是占用一个序列号(凡是消耗序列号的 TCP 报文段,一定需要对端确认。如果这个段没有收到确认,会一直重传直到达到指定的次数为止),该报文需要服务端确认。初始序列号(ISN)是由客户端随机生成的一个数字,下次发送数据序列号要加一。
-
第二次握手:服务端接收到客户端发送的SYN报文后,发送一个SYN报文和ACK报文给客户端。
SYN的序列号值是服务端随机生成的一个数字,ACK的作用是告诉发送端上次发送端SYN报文我收到了,ACK的确认号值是客户端发送过来的序列号值加一(ISN + 1),指定了发送端下次发送的序列号。
-
第三次握手:客户端接收到服务的SYN和ACK报文段后,发送一个ACK段给服务端,用来确认收到了服务端的SYN段。
因为该ACK段不携带数据,也不需要被确认,因此不消耗序列号。
总结 :TCP的三次握手主要就是交换彼此的初始序列号,还有就是交换一些辅助信息:最大段大小(MSS)、窗口大小(Win)、窗口缩放因子(WS)、是否支持选择确认(SACK_PERM)等。
TCP断开连接(四次挥手)
-
客户端发送一个FIN报文给服务端,自身连接状态由 ESTABLISHED 进入 FIN- WAIT-1。
此时客户端不能发送数据给服务端,但还能接收服务端数据。
-
服务端接收到FIN报文,回复一个ACK报文给客户端,进入 CLOSE_WAIT 状态,客户端收到ACK报文后进入 FIN- WAIT-2 状态。
-
服务端没有数据要发送后,发送FIN报文给客户端,然后进入 LAST-ACK 状态,等待客户端的ACK。
-
客户端收到第三步服务端发送的FIN报文后,回复一个ACK报文给服务端,进入 TIME- WAIT 状态,等待两个MSL(MSL报文最大生存时间,正常是30秒)后进入CLOSED状态, 服务端收到ACK后进入CLOSED状态。
TCP 端口
在传输层,我们根据端口来区分不同应用程序
-
端口类型
-
熟知的端口:熟知端口号由专门的机构由 IANA 分配和控制,范围为 0~1023。为了能让客户端能随时找到自己,服务端程序的端口必须要是固定的。很多熟知端口号已经被用就分配给了特定的应用,比如 HTTP 使用 80端口,HTTPS 使用 443 端口,ssh 使用 22 端口。
-
已登记的端口:已登记的端口不受 IANA 控制,不过由 IANA 登记并提供它们的使用情况清单。它的范围为 1024~49151,已登记的端口常见的端口号有:
MySQL:3306,Redis:6379,MongoDB:27017
-
临时端口:如果应用程序没有调用 bind() 函数将 socket 绑定到特定的端口上,那么 TCP 和 UDP 会为该 socket 分配一个唯一的临时端口。IANA 将 49152~65535 范围的端口称为临时端口(ephemeral port)或动态端口(dynamic port),也称为私有端口(private port),这些端口可供本地应用程序临时分配端口使用。
不同的操作系统实现会选择不同的范围分配临时端口,在 Linux 上能分配的端口范围由 /proc/sys/net/ipv4/ip_local_port_range 变量决定,一般 Linux 内核端口范围为 32768~60999
-
TCP是如何保证传输可靠性的
-
超时重传
-
快速重传
-
滑动窗口
-
拥塞控制
-
Nagle 算法
-
延迟确认
-
Keepalive