欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 艺术 > 深度解剖 TCP 三次握手 四次挥手

深度解剖 TCP 三次握手 四次挥手

2025/4/4 16:05:36 来源:https://blog.csdn.net/qq_45875349/article/details/146913536  浏览:    关键词:深度解剖 TCP 三次握手 四次挥手

说起后端面试中最“经典”的网络题,TCP 三次握手、四次挥手绝对是天王级别。它不仅是面试常客,更是区分“记答案”和“懂原理”的一道分水岭。

目录

一、TCP 基本认识

1. TCP 头格式有哪些?

2. 为什么需要 TCP 协议?工作在哪一层?

3. 什么是 TCP?

4. 如何唯一确定一个 TCP 连接?

5. UDP 与 TCP 的区别及应用场景?

6. TCP 与 UDP 可以使用同一个端口吗?

二、TCP 连接建立(三次握手)

1. TCP 三次握手过程是怎样的?

2. 如何在 Linux 系统中查看 TCP 状态?

3. 为什么是三次握手?不是两次、四次?

3.1 三次握手可以阻止重复历史连接的初始化(主要原因)

3.2 三次握手可以避免资源浪费

3.3 三次握手可以同步双方的初始序列号

4. 为什么每次建立 TCP 连接时,初始化的序列号(ISN)都要不一样?

4.1 避免旧连接数据影响新连接

4.2 防止攻击者伪造连接或注入数据(安全性)

5. 三次握手中每一次失败分别会发生什么?

🔴 第一次握手失败(客户端的 SYN 丢了)

🔴 第二次握手失败(服务端的 SYN+ACK 丢了)

🔴 第三次握手失败(客户端的 ACK 丢了)

✅ 总结成表(高效记忆)

6. 什么是 SYN 攻击?如何避免 SYN 攻击?

✅ 6.1 启用 SYN Cookies(首选)

✅ 6.2 增大TCP半连接队列

三、TCP断开连接

1. TCP 四次挥手过程是怎样的?

2. 为什么挥手需要四次?

3. 如果四次挥手中某一阶段丢包,会怎样?

4. 为什么 TIME_WAIT 等待时间是 2MSL?

1. ✅ 确保对方成功收到最后一个 ACK(第四次挥手)

2. ✅ 防止老连接的“延迟包”影响新连接

5. 为什么需要 TIME_WAIT 状态?

6. TIME_WAIT 状态太多有什么危害?

7. 如何优化 TIME_WAIT?

8. 服务端出现大量 TIME_WAIT 的原因有哪些?

9. 服务端出现大量 CLOSE_WAIT 的原因有哪些?

10. 如果已经建立了连接,但客户端突然宕机,怎么办?

11. 如果已经建立了连接,但服务端进程崩溃会发生什么?

情况一:服务端进程崩溃,但 socket 未立即释放(典型情况)

情况二:服务端进程崩溃时,系统及时关闭了 socket


一、TCP 基本认识

1. TCP 头格式有哪些?

TCP 头部结构包括:

  • 源端口号、目的端口号: 用于标识通信的两端应用程序,配合 IP 地址形成四元组(源IP、源端口、目标IP、目标端口)来唯一标识一个 TCP 连接。
  • 序列号(Sequence Number): 表示当前发送的数据在整个字节流中的起始位置。TCP 是面向字节流的协议,序列号确保数据能被按顺序接收与重组,也用于丢包重传。
  • 确认号(ACK Number): 用于接收方告诉发送方:“我已经收到数据,下一次请从这个序号开始发”。它是对序列号的响应,确保可靠接收。
  • 标志位(SYN, ACK, FIN, RST, PSH, URG)

共有 6 个常用控制位,用于控制连接状态和数据传输行为:

标志位

含义

SYN

建立连接(三次握手)

ACK

确认收到数据

FIN

请求断开连接(四次挥手)

RST

强制断开连接(异常重置)

PSH

推送数据,要求立即处理

URG

紧急数据(几乎不用)

  • 窗口大小(用于流量控制): 用于流量控制,表示接收方还能接收多少字节数据,防止发送方“发太快”,造成丢包或资源耗尽。
  • 校验和: 用于检测头部和数据是否在传输中被篡改或损坏,实现数据完整性校验。
  • 紧急指针(极少使用): 在 URG 位为 1 时,该字段指出紧急数据的最后一个字节位置。很少使用,多用于老式远程终端的中断信号。
  • 可选字段(如时间戳、窗口扩展)

👉 常考细节:TCP 是有状态的,每个字段都与可靠性、顺序性相关。


2. 为什么需要 TCP 协议?工作在哪一层?

TCP 是面向连接的、可靠的、字节流传输协议,工作在 传输层(第四层)。主要用于:

  • 数据完整性保障
  • 顺序传输
  • 拥塞控制与流量控制
  • 应答机制(ACK)
  • 错误重传(ARQ)

3. 什么是 TCP?

Transmission Control Protocol,用于提供可靠、有序的数据传输。对比 UDP,TCP 更重视传输质量而非速度。


4. 如何唯一确定一个 TCP 连接?

通过 源 IP + 源端口 + 目标 IP + 目标端口,即四元组唯一标识。


5. UDP 与 TCP 的区别及应用场景?

特性

TCP

UDP

连接方式

面向连接(三次握手)

无连接

是否可靠

否(不保证顺序和到达)

是否有序

是否流控/拥控

场景

文件传输、登录、数据库通信

视频流、DNS、VoIP


6. TCP 与 UDP 可以使用同一个端口吗?

**可以。**TCP 和 UDP 是两个不同协议栈,彼此独立监听各自的端口。


二、TCP 连接建立(三次握手)

1. TCP 三次握手过程是怎样的?

  1. 客户端发送 SYN,表示请求建立连接。
  2. 服务端回应 SYN+ACK,表示同意连接。
  3. 客户端发送 ACK,确认连接建立。

其中,第三次握手可以携带数据:

第三次握手时,连接已经“双方确认”成功建立

  • 客户端知道服务端能收;
  • 服务端已经发送 SYN+ACK,确认能接受连接请求;
  • 客户端这时发送 ACK(第三次握手)时,也可以顺便携带数据(如登录请求、认证信息等),并不会影响连接建立。

“第三次握手可以携带数据,但前两次握手即使携带,服务端一般也不会处理,是出于安全性和实现稳定性考虑。”


2. 如何在 Linux 系统中查看 TCP 状态?

TCP 的连接状态查看,在 Linux 可以通过 netstat -napt 命令查看。

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1042/sshd       
tcp        0     64 192.168.1.10:22         192.168.1.20:53624      ESTABLISHED 2071/sshd: user  
tcp6       0      0 :::80                   :::*                    LISTEN      1123/nginx       
tcp6       0      0 192.168.1.10:80         192.168.1.21:48912      TIME_WAIT   -

字段解释:

字段

含义

Proto

协议类型(TCP)

Recv-Q

接收队列长度(数据等待读)

Send-Q

发送队列长度(数据等待发送)

Local Address

本地地址 + 端口

Foreign Addr

对端地址 + 端口

State

TCP 状态(如 LISTEN、ESTABLISHED、TIME_WAIT)

PID/Program

对应的进程 ID 和进程名(如 sshd、nginx)


3. 为什么是三次握手?不是两次、四次?

三次握手不是为了麻烦,而是为了可靠、安全、高效地建立连接,防止伪连接、乱序号、资源浪费,是 TCP 保证“可靠传输”这件事的第一道防线。 两次握手并不能充分保证双方的接收与发送能力,四次握手多余。

3.1 三次握手可以阻止重复历史连接的初始化(主要原因)

🧠背景

如果只进行两次握手(SYN → SYN+ACK),那么旧连接遗留的 ACK 或 SYN+ACK 报文如果滞留在网络中,被新的连接误收,就可能导致服务端错误地认为这是一个新连接,从而错误建立连接

🧨 问题示例:

  1. 某个连接断开后,网络中仍残留上一次的 SYN 报文。
  2. 服务端收到这个旧 SYN,再次回复 SYN+ACK;
  3. 客户端收到 SYN+ACK 后,无法区分这个 ACK 是针对旧连接还是新连接。

如果此时没有第三次确认(客户端ACK),服务端就会直接认为连接建立成功,导致:

  • 创建无效连接;
  • 分配资源;
  • 导致服务异常。
3.2 三次握手可以避免资源浪费

如果只进行两次握手,服务端在收到 SYN 后立刻认为连接建立成功,并为其分配资源(如 socket、线程、内存缓存等),但:

  • 客户端可能永远不会回应(断电、网络问题或恶意攻击);
  • 服务端就会为这个“半连接”白白占用资源,直到超时清理。

⚠️ 现实中的攻击:SYN Flood 攻击

  • 攻击者伪造大量 SYN 报文,服务端不断分配资源等待 ACK;
  • 最终耗尽连接队列,正常用户无法建立连接。
3.3 三次握手可以同步双方的初始序列号

TCP 是面向字节流的协议,序列号(ISN)是确保数据能被可靠、有序接收的关键。

🤝 为什么要双方同步?

  • 客户端和服务端都需要告诉对方:
    • 我将以哪个序号开始发数据;
    • 我期望你从哪个序号开始发。

🚦 举例:

  • 第一次握手:客户端发送 SYN,告诉服务端“我从 ISN1 开始”;
  • 第二次握手:服务端发 SYN+ACK,表示“我从 ISN2 开始,同时收到了你的 ISN1”;
  • 第三次握手:客户端 ACK,表示“我知道你是 ISN2,准备接收”。

没有三次握手,至少有一方不会知道对方的初始序列号,就无法正常通信,数据可能被丢弃或错乱。

4. 为什么每次建立 TCP 连接时,初始化的序列号(ISN)都要不一样?

TCP 每次连接初始化时使用不同的序列号,主要是为了: 1)防止旧连接数据污染新连接; 2)防止攻击者伪造连接或注入数据; 3)满足协议规定的可靠性要求; 这能有效保证 TCP 连接的唯一性、安全性和健壮性

4.1 避免旧连接数据影响新连接

TCP 是一个可靠传输的字节流协议,在通信中依赖序列号(Sequence Number)来标识数据位置。

如果新建立的连接重复使用旧连接的序列号,可能发生以下风险:

🧨 场景风险:

  1. 某个连接已关闭,但网络中残留该连接未清除的旧数据包;
  2. 如果新连接使用了相同的四元组和相同的初始序列号
  3. 那么旧数据包会被新连接错误地识别为合法数据,从而:
    • 导致应用接收到脏数据;
    • 导致连接错乱甚至崩溃。
4.2 防止攻击者伪造连接或注入数据(安全性)

若序列号是固定或可预测的,攻击者可以构造:

  • 一个带有合适序列号的伪造数据包;
  • 服务端可能会误以为是合法客户端的数据;
  • 从而造成 TCP Session Hijacking(会话劫持)

所以操作系统通常会随机化初始序列号(ISN),避免攻击者预测。

Linux、Windows 都有各自的 ISN 随机生成算法,比如基于时间戳 + 哈希。

5. 三次握手中每一次失败分别会发生什么?

🔴 第一次握手失败(客户端的 SYN 丢了)
  • 服务端根本没收到请求,也就不会回复 SYN+ACK;
  • 客户端会在 RTO(重传超时)后重发 SYN
  • 通常重传几次(例如 Linux 默认 5 次);
  • 如果始终收不到响应,客户端认为连接失败,返回错误(如 Connection timed out)。

📌 这是最常见的失败场景,比如服务器不在线、防火墙阻断等。


🔴 第二次握手失败(服务端的 SYN+ACK 丢了)
  • 客户端收不到 SYN+ACK,就认为“请求还没回应”;
  • 客户端会继续重发第一次的 SYN;
  • 服务端收到重复 SYN,会重发 SYN+ACK,这是合法且预期内的行为;
  • 如果客户端在重试次数内收到 SYN+ACK,连接仍然可以成功建立;
  • 否则最终失败。

TCP 是可以应对服务端响应丢失的,依靠超时 + 重传机制。


🔴 第三次握手失败(客户端的 ACK 丢了)
  • 服务端处于 SYN_RECV 状态,没有收到 ACK,不会进入 ESTABLISHED
  • 服务端会认为客户端没有完成握手,于是会重发 SYN+ACK
  • 如果客户端仍在线,就会重发 ACK,完成连接;
  • 如果客户端已经崩溃或掉线,服务端会在一定时间后放弃连接(超时关闭)

⚠️ 注意:服务端不会立即分配大量资源,这也是 SYN Flood 防御的基础


✅ 总结成表(高效记忆)

握手步骤

谁发的

如果失败

后果

第一次(SYN)

客户端

服务端无响应

客户端重发 SYN,最终连接超时失败

第二次(SYN+ACK)

服务端

客户端收不到

客户端重发 SYN,服务端重发 SYN+ACK

第三次(ACK)

客户端

服务端收不到

服务端重发 SYN+ACK,等待 ACK 超时后关闭连接

6. 什么是 SYN 攻击?如何避免 SYN 攻击?

背景知识:TCP 三次握手

在 TCP 连接建立时,需要进行三次握手:

  1. 客户端发送 SYN 报文,请求建立连接;
  2. 服务器回复 SYN-ACK,表示接受请求;
  3. 客户端再发送 ACK 确认,连接建立。

💥 SYN 攻击原理

攻击者在三次握手过程中:

  • 只发送 SYN 报文,不发送最终的 ACK 确认
  • 服务器为了等待 ACK,会将连接信息保存到半连接队列(SYN queue)中;
  • 如果攻击者大量发起伪造 IP 的 SYN 请求,服务器资源会被耗尽,导致正常用户无法建立连接。

📉 本质:耗尽服务器的资源(连接队列/内存/CPU),从而造成拒绝服务

那么, 如何防御 SYN 攻击?

✅ 6.1 启用 SYN Cookies(首选)

Linux 内核的一项机制:在收到 SYN 时不立刻分配资源,而是通过加密算法生成一个 Cookie 存在 TCP 序号里,在收到 ACK 时再验证是否是合法连接。

正常 TCP 三次握手:

  1. 🧑 Client → Server :发送 SYN(seq = x)
  2. 🧑‍💻 Server → Client :返回 SYN+ACK(ack = x+1,seq = y)→ 此时服务器会保留连接状态(半连接)
  3. 🧑 Client → Server :返回 ACK(ack = y+1)→ 完成连接

📌 问题在于第 2 步,服务端会保留状态(占用内存和连接队列),攻击者只发送 SYN 就能把服务打满。

启用 SYN Cookies 后的流程(核心机制)

🌟 SYN Cookie 的精髓:“不保存状态信息,利用 TCP 序列号做校验”

  1. 🧑 Client → Server :发送 SYN(seq = x)
  2. 🧑‍💻 Server → Client :返回 Server: SYN + ACK, seq = Cookie, ack = x+1): 服务器收到后不直接保存状态,而是生成一个“cookie”,并作为 TCP 序列号返回。 Cookie = hash(client_ip, client_port, server_ip, server_port, MSS, timestamp, secret_key)。
  3. 🧑 Client → Server :返回 Client: ACK, seq = x+1, ack = Cookie+1,服务器收到 ACK 后,提取 ack-1 得到 cookie,并重新 hash 计算看是否一致:一致 → 说明客户端确实发送了 ACK,连接有效;不一致 → 说明是伪造或攻击请求,丢弃即可
6.2 增大TCP半连接队列

增大 TCP 半连接队列 ,要同时增大下面这三个参数:

  • 增大 net.ipv4.tcp_max_syn_backlog
  • 增大 listen() 函数中的 backlog
  • 增大 net.core.somaxconn

三、TCP断开连接

1. TCP 四次挥手过程是怎样的?

为什么需要四次挥手呢?

因为 TCP 是全双工通信协议,断开连接必须 双方都同意关闭自己的发送方向

所以:

  • 一方主动关闭 → FIN(表示我不发了);
  • 另一方要 ACK(我知道你不发了);
  • 然后自己也要主动发 FIN(我也不发了);
  • 最后再 ACK(我确认你也不发了);

于是就有了四步操作 —— 四次挥手!这里第三次和第四次是不能合并的,请求方请求断开之后,另一方回复AC之后,自己可能还有数据需要发送,所有只能再自己的数据发送完之后,再回复FIN,表示“我没有什么想说的了,就这样吧”。

  1. 客户端发送 FIN,请求关闭连接;
  2. 服务端 ACK;
  3. 服务端处理完后发送 FIN;
  4. 客户端 ACK,进入 TIME_WAIT,连接关闭。

2. 为什么挥手需要四次?

TCP 是双向通信,发送和接收都要分别关闭,FIN 和 ACK 分离就是为了让两边各自独立关闭发送方向


3. 如果四次挥手中某一阶段丢包,会怎样?

  • 第一次(FIN)丢:客户端超时重传机制,重传 FIN报文,重发次数由 tcp_orphan_retries 参数控制。当客户端重传 FIN 报文的次数超过 tcp_orphan_retries 后等待一段时间,如果还是没能收到第二次挥手,那么直接进入到close状态。
  • 第二次(ACK)丢:客户端会重发 FIN,直到收到服务端的ACK,或者到达最大的重传次数。
  • 第三次(FIN)丢:服务端重发FIN,同上。
  • 第四次(ACK)丢:服务端重发 FIN 或超时退出。

4. 为什么 TIME_WAIT 等待时间是 2MSL?

MSL(Maximum Segment Lifetime) 是数据包在网络中存在的最长时间。在实践中,一般认为 MSL ≈ 60 秒 。

1. ✅ 确保对方成功收到最后一个 ACK(第四次挥手)
  • 如果第四次的 ACK 丢失,服务端会重发 FIN;
  • 客户端处于 TIME_WAIT 状态时,可以接收并再次发送 ACK;
  • 否则服务端无法正常关闭连接。

📌 这是可靠传输模型下 ACK 机制的收尾保障

2. ✅ 防止老连接的“延迟包”影响新连接
  • 如果不等待,客户端关闭后马上重用该四元组(IP + 端口)建立新连接;
  • 网络中还在“漂浮”的旧连接数据包可能会送到新连接上,造成混乱或安全问题。

📌 这是保护新连接的完整性与隔离性


5. 为什么需要 TIME_WAIT 状态?

TIME_WAIT 的持续时间之所以是 2 倍 MSL,主要是为了保证: 1)最后一个 ACK 若丢失,能接收对方重发的 FIN 并再次 ACK; 2)确保网络中旧连接的残留数据不会影响后续建立的新连接;

这个设计体现了 TCP 在连接释放时对可靠性与安全性的高度重视,是协议稳健性的重要体现。

1)最后一个 ACK 若丢失,能接收对方重发的 FIN 并再次 ACK

如果客户端(主动关闭方)最后一次 ACK 报文(第四次挥手)在网络中丢失了,那么按照 TCP 可靠性原则,服务端(被动关闭方)会重发 FIN 报文。

假设客户端没有 TIME WAIT 状态,而是在发完最后一次回 ACK 报文就直接进入 CLOSE 状态,如果该ACK 报文丢失了,服务端则重传的 FIN 报文,而这时客户端已经进入到关闭状态了,在收到服务端重传的FIN 报文后,就会回 RST 报文。

为了防止这种情况出现,客户端必须等待足够长的时间,确保服务端能够收到 ACK,如果服务端没有收到ACK,那么就会触发 TCP 重传机制,服务端会重新发送一个 FIN,这样一去一来刚好两个 MSL的时间。

2)防止端口快速重用(相同四元组)导致旧连接干扰新连接。

为了防止历史连接中的数据,被后面相同四元组的连接错误的接收,因此 TCP 设计了 TIME WAIT 状态状态会持续 2MSL时长,这个时间足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的,


6. TIME_WAIT 状态太多有什么危害?

客户端和服务端 TIME_WAIT 过多,造成的影响是不同的。

TIME_WAIT 状态出现在主动断开连接的一方,客户端 TIME_WAIT 多,主要会导致端口资源耗尽、连接无法发起;服务端 TIME_WAIT 多,则会导致系统内核资源被大量占用,性能下降。 优化方向分别是:客户端应复用端口、使用长连接;服务端则应尽量让对端主动断开、减少短连接操作,提升系统承压能力。


7. 如何优化 TIME_WAIT?

在高并发系统中,TIME_WAIT 状态过多是一个常见但严重的问题,特别是在大量短连接的场景下。由于 TCP 协议规定,主动关闭连接的一方需要进入 TIME_WAIT 状态并持续 2 倍的最大报文生存时间(2MSL),这会导致系统内产生大量处于 TIME_WAIT 状态的连接,从而消耗本地端口资源、占用内核连接表、增加内存和 CPU 压力。客户端因此可能遭遇“端口耗尽”,服务端则可能面临“吞吐下降”、“连接失败”或“系统抖动”等现象。

针对这一问题,优化方向主要有三个:能不断就别断、要断就让客户端断、必须断就减少代价。也就是说,优先使用长连接连接池,减少不必要的断连操作;其次,尽量让客户端发起断连,将 TIME_WAIT 的压力转移出服务端;最后,必要时可以启用内核参数优化,如 tcp_tw_reuse 以实现快速端口复用。

具体的优化措施包括:

  1. 使用 HTTP Keep-Alive、数据库连接池、gRPC Channel 复用 等长连接机制,降低连接断开频率;
  2. 设置客户端主动关闭连接,避免服务端产生大量 TIME_WAIT;
  3. 启用 net.ipv4.tcp_tw_reuse=1,在安全场景下复用 TIME_WAIT 状态端口;
  4. 扩大本地可用端口范围,例如调整 ip_local_port_range"1024 65535"
  5. 利用 Nginx、HAProxy 等反向代理中间层对后端请求进行聚合复用;
  6. 极端场景下,酌情缩短 tcp_fin_timeout 时间,加快资源释放(需权衡协议可靠性)。

总结为一句话:“能不断,就别断;要断,别让服务端断;必须断,用 reuse;还不行?加端口、用代理、建连接池!” 这是面对 TIME_WAIT 压力的全链路实战策略。


8. 服务端出现大量 TIME_WAIT 的原因有哪些?

正常情况下 TIME_WAIT 在主动关闭方产生,如果服务端主动关闭连接,就会积累此状态。


9. 服务端出现大量 CLOSE_WAIT 的原因有哪些?

  1. 什么是 CLOSE_WAIT 状态?

在 TCP 的四次挥手中,当 对端(通常是客户端)主动关闭连接并发送 FIN 报文,服务端收到这个 FIN 后,会立刻进入 CLOSE_WAIT 状态

此时,服务端表示:

“我知道你不发数据了,我也准备关闭连接,但我还没真正关闭。”

👉 服务端还没有执行 close() 操作,连接仍然存在。

  1. 为什么服务端会出现大量 CLOSE_WAIT

服务端收到了客户端的 FIN 报文,但没有及时关闭 socket(没有调用 close())

也就是说,服务端收到了“断开连接”的信号,但应用层没有响应或者处理不当,导致连接一直挂起在 CLOSE_WAIT 状态。


10. 如果已经建立了连接,但客户端突然宕机,怎么办?

如果客户端在连接建立后突然 宕机,服务端最初并不会立即察觉,连接仍处于 ESTABLISHED 状态。只有当服务端尝试 发送数据或启用了 TCP KeepAlive / 应用层心跳时,才能检测到对方失联。

如果服务端一直不会发送数据,再看服务端有没有开启 TCP keepalive 机制?如果有开启,服务端在一段时间没有进行数据交互时,会触发 TCP keepalive 机制,探测对方是否存中在,如果探测到对方已经消亡,则会断开自身的TCP 连接;如果没有开启,服务端的 TCP 连接会一直存在,并且一直保持在 ESTABLISHED 状态。

如果「客户端进程崩溃」,客户端的进程在发生崩溃的时候,内核会发送 FIN 报文,与服务端进行四次挥手。


11. 如果已经建立了连接,但服务端进程崩溃会发生什么?

情况一:服务端进程崩溃,但 socket 未立即释放(典型情况)
  • 服务端进程异常退出,操作系统可能还保留着 TCP 连接状态(比如 socket 没被 close);
  • 这时候,客户端仍然认为连接是 ESTABLISHED,直到它尝试:
    • 发送数据;
    • 或等待响应超时;
    • 或操作系统发送 RST(复位)包。
情况二:服务端进程崩溃时,系统及时关闭了 socket

自动 close socket

  • 操作系统会执行 正常 TCP 四次挥手断开流程
  • 客户端会收到 FIN;
  • 连接进入 CLOSE_WAITTIME_WAIT 状态,最终关闭;
  • 客户端不会报错,只是读取到 EOF(end of stream)。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词