乐闻世界logo
搜索文章和话题

TCP

TCP(Transmission Control Protocol,传输控制协议)是一种广泛使用的网络通信协议,属于互联网协议套件的核心协议之一。它位于 OSI 模型的传输层,提供了一种可靠的、面向连接的通信方式,确保数据包在两个网络设备之间正确无误地传递。
TCP
查看更多相关内容
TCP Nagle 算法的原理和作用是什么?# TCP Nagle 算法详解 Nagle 算法是一种用于减少网络中小数据包数量的算法,通过合并多个小数据包来提高传输效率。 ## Nagle 算法原理 ### 算法规则 1. **数据包小于 MSS**:如果待发送的数据包小于 MSS(最大报文段大小) 2. **等待 ACK**:等待前一个数据包的 ACK 到达 3. **合并发送**:将多个小数据包合并成一个大数据包发送 4. **超时机制**:如果 ACK 超时未到达,立即发送当前数据包 ### 工作流程 ``` 发送方 → [数据包1 < MSS] → 等待ACK → [数据包2 < MSS] → 合并发送 → 接收方 ``` ## Nagle 算法的优势 ### 1. 减少网络负载 - **减少数据包数量**:合并多个小数据包,减少网络中的数据包数量 - **降低带宽消耗**:减少 TCP 首部开销(每个数据包 20-60 字节) - **提高网络效率**:减少路由器和交换机的处理负担 ### 2. 提高吞吐量 - **减少 ACK 数量**:合并发送减少 ACK 数量 - **降低延迟**:减少往返次数 - **提高带宽利用率**:更充分地利用网络带宽 ## Nagle 算法的问题 ### 1. 增加延迟 - **等待 ACK**:需要等待前一个数据包的 ACK 才能发送下一个数据包 - **实时性差**:对实时性要求高的应用影响较大 - **延迟累积**:多个小数据包的延迟会累积 ### 2. 与延迟 ACK 冲突 - **延迟 ACK**:接收方延迟发送 ACK,减少 ACK 数量 - **双重延迟**:Nagle 算法等待 ACK + 延迟 ACK = 更大的延迟 - **影响性能**:可能导致 40ms、200ms 甚至更大的延迟 ## 禁用 Nagle 算法 ### 适用场景 - **实时性要求高**:在线游戏、实时音视频等 - **小数据包频繁**:需要立即发送小数据包 - **低延迟优先**:延迟比吞吐量更重要 ### 配置方法 #### Linux 系统配置 ```bash # 禁用 Nagle 算法(TCP_NODELAY) sysctl -w net.ipv4.tcp_low_latency=1 ``` #### 编程配置(Python) ```python import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) ``` #### 编程配置(C) ```c int flag = 1; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); ``` ## Nagle 算法 vs 延迟 ACK ### Nagle 算法 - **位置**:发送方 - **目的**:减少小数据包数量 - **机制**:等待 ACK 到达后再发送下一个数据包 ### 延迟 ACK - **位置**:接收方 - **目的**:减少 ACK 数量 - **机制**:延迟发送 ACK,等待多个数据包到达后一起确认 ### 冲突解决 - **禁用 Nagle 算法**:发送方立即发送小数据包 - **禁用延迟 ACK**:接收方立即发送 ACK - **权衡**:根据应用场景选择合适的策略 ## 相关问题 - 为什么 Nagle 算法会增加延迟? - 什么时候应该禁用 Nagle 算法? - Nagle 算法和延迟 ACK 如何配合使用?
计算机基础 · 2月21日 17:10
TCP Keep-Alive 机制的作用和原理是什么?# TCP Keep-Alive 机制详解 TCP Keep-Alive 是一种检测连接是否存活的机制,用于及时发现和清理失效的连接。 ## Keep-Alive 机制原理 ### 工作流程 1. **空闲等待**:连接在空闲一段时间后(默认 2 小时),开始发送 Keep-Alive 探测包 2. **发送探测**:发送一个不包含数据的 TCP 报文段,序列号为当前序列号减 1 3. **等待响应**: - 收到 ACK:连接正常,重置计时器 - 收到 RST:连接被对方重置,关闭连接 - 超时未响应:连接可能失效,继续探测 ### 探测参数 - **tcp_keepalive_time**:连接空闲多长时间后开始发送探测(默认 7200 秒) - **tcp_keepalive_intvl**:探测包发送间隔(默认 75 秒) - **tcp_keepalive_probes**:最大探测次数(默认 9 次) ## Keep-Alive 的作用 ### 1. 检测失效连接 - 网络中断、设备故障等导致连接失效 - 及时发现并清理失效连接,释放资源 ### 2. 防止连接假死 - 应用层未正常关闭连接,但连接已失效 - Keep-Alive 可以检测到这种情况 ### 3. 保持连接活跃 - 某些中间设备(如 NAT)会清理长时间空闲的连接 - Keep-Alive 可以保持连接不被清理 ## Keep-Alive 的缺点 ### 1. 资源消耗 - 需要维护连接状态和计时器 - 大量连接时,Keep-Alive 会增加系统负担 ### 2. 误判风险 - 网络延迟可能导致误判连接失效 - 可能误关闭正常但延迟高的连接 ### 3. 不及时 - 默认等待时间较长(2 小时) - 无法快速检测到连接失效 ## 应用层心跳 vs Keep-Alive ### Keep-Alive - **优点**:操作系统级别支持,无需应用层实现 - **缺点**:参数固定,不够灵活,等待时间长 ### 应用层心跳 - **优点**:灵活可控,可以携带业务数据,检测更及时 - **缺点**:需要应用层实现,增加开发成本 ## 配置示例 ### Linux 系统配置 ```bash # 查看 Keep-Alive 参数 sysctl net.ipv4.tcp_keepalive_time sysctl net.ipv4.tcp_keepalive_intvl sysctl net.ipv4.tcp_keepalive_probes # 修改 Keep-Alive 参数 sysctl -w net.ipv4.tcp_keepalive_time=600 sysctl -w net.ipv4.tcp_keepalive_intvl=30 sysctl -w net.ipv4.tcp_keepalive_probes=3 ``` ### 编程配置(Python) ```python import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 600) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 30) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 3) ``` ## 相关问题 - Keep-Alive 和心跳包有什么区别? - 如何优化 Keep-Alive 参数? - 为什么默认 Keep-Alive 时间这么长?
计算机基础 · 2月21日 17:10
TCP 流量控制的滑动窗口机制是如何工作的?# TCP 流量控制机制详解 TCP 流量控制是防止发送方发送速度过快导致接收方缓冲区溢出的关键机制。 ## 滑动窗口机制 ### 窗口大小 - **接收窗口(rwnd)**:接收方通告的可用缓冲区大小 - **拥塞窗口(cwnd)**:发送方根据网络状况计算的窗口大小 - **实际发送窗口**:min(rwnd, cwnd),即取两者中的较小值 ### 工作原理 1. **接收方通告**:在 TCP 报文段的窗口字段中通告当前可用的接收窗口大小 2. **发送方调整**:发送方根据接收方的窗口大小调整发送速率 3. **零窗口**:当接收方缓冲区满时,通告窗口大小为 0 4. **窗口探测**:发送方定期发送零窗口探测报文,查询接收方窗口是否可用 ## 流量控制过程 ### 正常情况 - 接收方有足够缓冲区时,窗口大小保持较大值 - 发送方可以连续发送多个报文段 - 接收方处理数据后,更新窗口大小并通告发送方 ### 缓冲区紧张 - 接收方缓冲区接近满时,减小窗口大小 - 发送方相应减少发送速率 - 避免数据丢失和重传 ### 零窗口处理 - 接收方缓冲区满时,通告窗口大小为 0 - 发送方停止发送数据,但保持连接 - 定期发送零窗口探测(1 字节数据) - 接收方有空间后,更新窗口大小 ## 窗口更新的时机 - **接收数据后**:处理完数据,释放缓冲区空间 - **应用层读取数据**:从接收缓冲区读取数据后 - **零窗口探测响应**:响应发送方的探测报文 ## 相关问题 - 流量控制和拥塞控制的区别是什么? - 为什么需要零窗口探测机制? - 滑动窗口如何影响 TCP 的吞吐量?
计算机基础 · 2月21日 17:09
TCP 拥塞控制的四个算法是什么?# TCP 拥塞控制机制详解 TCP 拥塞控制是网络稳定性的关键机制,防止网络拥塞导致的数据包丢失和性能下降。 ## 拥塞控制的四个核心算法 ### 1. 慢启动(Slow Start) - **初始状态**:cwnd(拥塞窗口)初始化为 1 个 MSS(最大报文段大小) - **指数增长**:每收到一个 ACK,cwnd 加倍,每经过一个 RTT,cwnd 翻倍 - **阈值触发**:当 cwnd 达到 ssthresh(慢启动阈值)时,进入拥塞避免阶段 - **目的**:快速探测网络可用带宽,避免一开始就发送大量数据导致拥塞 ### 2. 拥塞避免(Congestion Avoidance) - **线性增长**:每经过一个 RTT,cwnd 增加 1 个 MSS - **保守策略**:增长速度比慢启动慢,避免突然导致网络拥塞 - **触发条件**:cwnd ≥ ssthresh 时进入此阶段 ### 3. 快重传(Fast Retransmit) - **触发条件**:收到 3 个重复 ACK(duplicate ACK) - **立即重传**:不等待 RTO(重传超时)到期,立即重传丢失的报文段 - **原因**:重复 ACK 表明中间报文段丢失,但后续报文段已到达 ### 4. 快恢复(Fast Recovery) - **cwnd 调整**:将 cwnd 设置为 ssthresh + 3 × MSS - **ssthresh 更新**:ssthresh = cwnd / 2 - **后续处理**:每收到一个重复 ACK,cwnd 加 1;收到新数据的 ACK 时,cwnd = ssthresh,进入拥塞避免 ## 拥塞发生时的处理 - **超时重传**:ssthresh = cwnd / 2,cwnd = 1,重新进入慢启动 - **快重传触发**:ssthresh = cwnd / 2,cwnd = ssthresh,进入快恢复 ## 相关问题 - 慢启动和拥塞避免的区别是什么? - 为什么需要 3 个重复 ACK 才触发快重传? - 如何优化 TCP 拥塞控制以提高网络性能?
计算机基础 · 2月21日 17:09
TCP 四次挥手的过程和原理是什么?# TCP 四次挥手详解 TCP 四次挥手是终止连接的过程,确保双方都能安全地关闭连接并释放资源。 ## 挥手过程 1. **第一次挥手(FIN)**:客户端发送 FIN=1、seq=u 的报文段,进入 FIN_WAIT_1 状态,表示客户端没有数据要发送了 2. **第二次挥手(ACK)**:服务器收到 FIN 后,发送 ACK=1、seq=v、ack=u+1 的报文段,进入 CLOSE_WAIT 状态,客户端收到后进入 FIN_WAIT_2 状态 3. **第三次挥手(FIN)**:服务器发送 FIN=1、ACK=1、seq=w、ack=u+1 的报文段,进入 LAST_ACK 状态,表示服务器也没有数据要发送了 4. **第四次挥手(ACK)**:客户端收到 FIN 后,发送 ACK=1、seq=u+1、ack=w+1 的报文段,进入 TIME_WAIT 状态,服务器收到后进入 CLOSED 状态 ## 为什么需要四次挥手 - **TCP 是全双工协议**:每个方向都必须单独关闭 - **第二次挥手只确认了客户端的关闭请求**:服务器可能还有数据要发送给客户端,所以不能立即发送 FIN - **第三次挥手是服务器主动关闭**:服务器确认没有数据要发送后,才发送 FIN - **TIME_WAIT 状态**:客户端需要等待 2MSL(最大报文生存时间),确保最后一个 ACK 能够到达服务器 ## TIME_WAIT 状态的作用 - **确保最后的 ACK 能够到达服务器**:如果 ACK 丢失,服务器会重传 FIN,客户端可以重新发送 ACK - **等待所有旧报文段消失**:确保网络中所有旧报文段都已过期,避免影响新连接 ## 相关问题 - 为什么 TIME_WAIT 状态需要等待 2MSL? - 如果服务器在 TIME_WAIT 状态之前就关闭了会发生什么? - 大量 TIME_WAIT 状态的连接会对服务器造成什么影响?
计算机基础 · 2月21日 17:09
TCP 可靠传输的保障机制有哪些?# TCP 可靠传输机制详解 TCP 可靠传输是 TCP 协议的核心特性,确保数据在不可靠的网络环境中能够正确、有序、无丢失地传输。 ## 可靠传输的保障机制 ### 1. 序列号和确认应答 - **序列号(Sequence Number)**:每个字节都有唯一的序列号,标识数据在流中的位置 - **确认应答(ACK)**:接收方收到数据后发送 ACK,确认已收到的数据 - **累积确认**:ACK 号码表示期望收到的下一个字节序列号 - **作用**:确保数据按序到达,检测丢失的数据包 ### 2. 重传机制 #### 超时重传(RTO) - **RTO 计算**:基于 RTT(往返时间)动态计算,通常 RTO = RTT + 4 × RTT 方差 - **触发条件**:发送数据后,在 RTO 时间内未收到 ACK - **指数退避**:每次重传后,RTO 加倍,避免网络拥塞时频繁重传 #### 快速重传 - **触发条件**:收到 3 个重复 ACK - **优势**:不等待 RTO 到期,立即重传丢失的报文段 - **效率**:比超时重传更快恢复数据传输 ### 3. 校验和 - **计算范围**:TCP 首部、数据和伪首部(包含 IP 地址等) - **作用**:检测数据传输过程中的错误 - **处理**:校验和错误时,直接丢弃报文段,不发送 ACK ### 4. 数据排序 - **问题**:网络中数据包可能乱序到达 - **解决**:接收方根据序列号重新排序 - **缓存**:乱序到达的数据先缓存,等待缺失数据到达后一起交付应用层 ### 5. 流量控制 - **滑动窗口**:接收方通告可用缓冲区大小 - **防止溢出**:避免发送方发送过快导致接收方缓冲区溢出 ### 6. 拥塞控制 - **慢启动**:逐步增加发送速率 - **拥塞避免**:线性增长,避免网络拥塞 - **快重传和快恢复**:快速响应丢包,恢复传输 ## 可靠传输的权衡 - **延迟 vs 可靠性**:重传机制增加延迟,但提高可靠性 - **效率 vs 安全**:校验和增加开销,但确保数据完整性 - **吞吐量 vs 稳定性**:拥塞控制降低吞吐量,但保持网络稳定 ## 相关问题 - TCP 如何处理乱序到达的数据包? - RTO 如何动态计算和调整? - 为什么需要快速重传机制?
计算机基础 · 2月21日 17:09
TCP 和 UDP 的主要区别是什么?# TCP 与 UDP 的区别详解 TCP 和 UDP 是传输层最主要的两个协议,它们在设计理念和适用场景上有显著差异。 ## 核心区别 ### 1. 连接性 - **TCP**:面向连接,需要三次握手建立连接,四次挥手断开连接 - **UDP**:无连接,直接发送数据,不需要建立连接 ### 2. 可靠性 - **TCP**:可靠传输,提供确认应答、重传、校验和等机制 - **UDP**:不可靠传输,不保证数据到达,可能丢包、乱序 ### 3. 有序性 - **TCP**:保证数据按序到达,通过序列号和确认应答实现 - **UDP**:不保证顺序,数据包可能乱序到达 ### 4. 流量控制 - **TCP**:有滑动窗口机制,防止发送过快导致接收方缓冲区溢出 - **UDP**:无流量控制,发送方不关心接收方处理能力 ### 5. 拥塞控制 - **TCP**:有拥塞控制机制(慢启动、拥塞避免、快重传、快恢复) - **UDP**:无拥塞控制,可能导致网络拥塞 ### 6. 传输效率 - **TCP**:首部开销大(20-60 字节),传输效率相对较低 - **UDP**:首部开销小(8 字节),传输效率高 ### 7. 传输方式 - **TCP**:面向字节流,将数据看作连续的字节流 - **UDP**:面向报文,保留报文边界,一个报文就是一个数据单元 ### 8. 连接数量 - **TCP**:一对一连接,点对点通信 - **UDP**:支持一对一、一对多、多对多、多对一的通信 ## 适用场景 ### TCP 适用场景 - **文件传输**:FTP、HTTP、HTTPS 等,需要可靠传输 - **邮件传输**:SMTP、POP3、IMAP 等 - **远程登录**:SSH、Telnet 等 - **需要可靠性的应用**:数据库连接、金融交易等 ### UDP 适用场景 - **实时音视频**:视频会议、直播、VoIP 等,对延迟敏感 - **在线游戏**:FPS、MOBA 等,需要低延迟 - **DNS 查询**:域名解析,数据量小,要求快速响应 - **广播和多播**:IGMP、DHCP 等 - **实时监控**:传感器数据上报等 ## 性能对比 | 特性 | TCP | UDP | |------|-----|-----| | 连接建立 | 需要(3 次握手) | 不需要 | | 可靠性 | 高 | 低 | | 传输效率 | 较低 | 较高 | | 延迟 | 较高 | 较低 | | 资源消耗 | 较高 | 较低 | | 数据顺序 | 保证 | 不保证 | ## 相关问题 - 为什么视频通话使用 UDP 而不是 TCP? - TCP 和 UDP 可以同时使用吗? - 如何在 UDP 上实现可靠传输?
计算机基础 · 2月21日 17:09
TCP TIME_WAIT 状态的作用和问题是什么?# TCP TIME_WAIT 状态详解 TIME_WAIT 是 TCP 连接关闭过程中的一个重要状态,对网络稳定性和连接复用有重要影响。 ## TIME_WAIT 状态概述 ### 状态定义 - **出现时机**:主动关闭方在发送第四次挥手(ACK)后进入 TIME_WAIT 状态 - **持续时间**:2MSL(Maximum Segment Lifetime,最大报文生存时间) - **MSL 定义**:报文在网络中能够存在的最长时间,通常为 30 秒到 2 分钟 ### 状态转换 ``` ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED ``` ## TIME_WAIT 状态的作用 ### 1. 确保最后的 ACK 能够到达 - **问题**:如果第四次挥手的 ACK 丢失,服务器会重传 FIN - **解决**:TIME_WAIT 状态等待 2MSL,确保有时间接收服务器的重传 FIN - **机制**:如果收到重传的 FIN,可以重新发送 ACK ### 2. 等待所有旧报文段消失 - **问题**:网络中可能存在延迟的旧报文段 - **解决**:等待 2MSL,确保所有旧报文段都已过期 - **目的**:避免旧报文段影响新连接 ## TIME_WAIT 状态的问题 ### 1. 资源占用 - **内存占用**:每个 TIME_WAIT 连接占用内存 - **文件描述符**:占用文件描述符,可能达到系统上限 - **端口占用**:占用本地端口,可能导致端口耗尽 ### 2. 连接数限制 - **四元组限制**:TCP 连接由源 IP、源端口、目的 IP、目的端口确定 - **端口数量有限**:客户端可用端口数量有限(约 6 万个) - **高并发场景**:大量 TIME_WAIT 连接可能导致无法建立新连接 ## 解决方案 ### 1. 调整 MSL 时间 - **参数**:`net.ipv4.tcp_fin_timeout` - **作用**:缩短 TIME_WAIT 状态的持续时间 - **风险**:可能导致旧报文段影响新连接 ### 2. 启用端口复用 - **参数**:`SO_REUSEADDR`、`SO_REUSEPORT` - **作用**:允许 TIME_WAIT 状态的端口被新连接使用 - **注意**:需要确保新连接的四元组与旧连接不同 ### 3. 增加本地端口范围 - **参数**:`net.ipv4.ip_local_port_range` - **作用**:增加可用端口数量 - **限制**:端口数量仍然有限 ### 4. 优化连接管理 - **连接池**:复用现有连接,减少频繁建立和关闭连接 - **长连接**:使用长连接代替短连接 - **负载均衡**:分散连接到多个服务器 ## 配置示例 ### Linux 系统配置 ```bash # 缩短 TIME_WAIT 超时时间 sysctl -w net.ipv4.tcp_fin_timeout=30 # 启用 TCP 时间戳 sysctl -w net.ipv4.tcp_timestamps=1 # 启用端口复用 sysctl -w net.ipv4.tcp_tw_reuse=1 # 增加本地端口范围 sysctl -w net.ipv4.ip_local_port_range="1024 65535" ``` ### 编程配置(Python) ```python import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) ``` ## 相关问题 - 为什么 TIME_WAIT 状态需要等待 2MSL? - 如何快速复用 TIME_WAIT 状态的端口? - 大量 TIME_WAIT 连接会对系统造成什么影响?
计算机基础 · 2月21日 17:09
TCP SYN Flood 攻击的原理和防御方法是什么?# TCP SYN Flood 攻击及防御详解 SYN Flood 是一种常见的 DDoS 攻击方式,利用 TCP 三次握手的漏洞,耗尽服务器资源,导致服务不可用。 ## SYN Flood 攻击原理 ### 攻击过程 1. **发送大量 SYN 包**:攻击者向服务器发送大量 TCP SYN 报文段 2. **伪造源 IP**:使用伪造的或随机的源 IP 地址 3. **服务器响应**:服务器收到 SYN 后,发送 SYN+ACK,并进入 SYN_RCVD 状态 4. **等待 ACK**:服务器等待第三次握手(ACK),但由于源 IP 是伪造的,永远不会收到 ACK 5. **资源耗尽**:大量连接处于 SYN_RCVD 状态,耗尽服务器的连接资源 ### 攻击危害 - **连接队列满**:服务器的半连接队列(SYN 队列)被填满 - **无法建立新连接**:正常的连接请求无法处理 - **内存耗尽**:每个半连接占用内存,大量半连接导致内存耗尽 - **CPU 占用高**:处理大量 SYN 包消耗 CPU 资源 ## 防御措施 ### 1. SYN Cookies - **原理**:不保存半连接状态,将连接信息编码在 SYN+ACK 的序列号中 - **优势**:不占用连接队列资源,防御能力强 - **实现**:服务器根据源 IP、源端口、目的 IP、目的端口等信息生成 Cookie - **验证**:收到 ACK 时,验证 Cookie 是否正确 ### 2. 增加半连接队列大小 - **参数**:`net.ipv4.tcp_max_syn_backlog` - **作用**:增加半连接队列容量,提高抗攻击能力 - **限制**:无法从根本上解决问题,只是延缓资源耗尽 ### 3. 缩短超时时间 - **参数**:`net.ipv4.tcp_synack_retries`、`net.ipv4.tcp_syn_retries` - **作用**:减少半连接的存活时间,快速释放资源 - **权衡**:可能影响正常连接的建立 ### 4. 限制 SYN 发送频率 - **原理**:限制单个 IP 地址的 SYN 包发送频率 - **实现**:使用 iptables、防火墙等工具 - **效果**:减少攻击流量,但可能误伤正常用户 ### 5. 启用 RST Cookie - **原理**:对可疑的 SYN 包发送 RST,要求客户端重新发起连接 - **效果**:过滤掉伪造 IP 的攻击流量 ## 配置示例 ### Linux 系统配置 ```bash # 启用 SYN Cookies sysctl -w net.ipv4.tcp_syncookies=1 # 增加半连接队列大小 sysctl -w net.ipv4.tcp_max_syn_backlog=8192 # 缩短超时时间 sysctl -w net.ipv4.tcp_synack_retries=2 sysctl -w net.ipv4.tcp_syn_retries=2 # 限制 SYN 发送频率 iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT iptables -A INPUT -p tcp --syn -j DROP ``` ## 相关问题 - SYN Cookies 的实现原理是什么? - 如何检测 SYN Flood 攻击? - 除了 SYN Flood,还有哪些 TCP 相关的攻击方式?
计算机基础 · 2月21日 17:09