TCP网络协议

165 阅读4分钟

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连接建立(三次握手)

  1. 第一次握手:客户端发送一个 SYN 报文段。

    该报文不携带数据,但是占用一个序列号(凡是消耗序列号的 TCP 报文段,一定需要对端确认。如果这个段没有收到确认,会一直重传直到达到指定的次数为止),该报文需要服务端确认。初始序列号(ISN)是由客户端随机生成的一个数字,下次发送数据序列号要加一。

  2. 第二次握手:服务端接收到客户端发送的SYN报文后,发送一个SYN报文和ACK报文给客户端。

    SYN的序列号值是服务端随机生成的一个数字,ACK的作用是告诉发送端上次发送端SYN报文我收到了,ACK的确认号值是客户端发送过来的序列号值加一(ISN + 1),指定了发送端下次发送的序列号。

  3. 第三次握手:客户端接收到服务的SYN和ACK报文段后,发送一个ACK段给服务端,用来确认收到了服务端的SYN段。

    因为该ACK段不携带数据,也不需要被确认,因此不消耗序列号。

总结 :TCP的三次握手主要就是交换彼此的初始序列号,还有就是交换一些辅助信息:最大段大小(MSS)、窗口大小(Win)、窗口缩放因子(WS)、是否支持选择确认(SACK_PERM)等。

TCP断开连接(四次挥手)

  1. 客户端发送一个FIN报文给服务端,自身连接状态由 ESTABLISHED 进入 FIN- WAIT-1。

    此时客户端不能发送数据给服务端,但还能接收服务端数据。

  2. 服务端接收到FIN报文,回复一个ACK报文给客户端,进入 CLOSE_WAIT 状态,客户端收到ACK报文后进入 FIN- WAIT-2 状态。

  3. 服务端没有数据要发送后,发送FIN报文给客户端,然后进入 LAST-ACK 状态,等待客户端的ACK。

  4. 客户端收到第三步服务端发送的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