TCP 篇
TCP 是互联网最"靠谱"的协议——它保证你发的数据不丢、不重、按顺序到达。微信聊天、文件下载、网页浏览,背后都是 TCP 在保驾护航。
你打电话——先拨号,对方接起"喂?",你说"听得到吗?",对方说"听得到"——然后才开始说正事。
说完你说"我说完了",对方说"好的",你再说"拜拜",对方也说"拜拜"——挂断。
这个过程就是 TCP 的"三次握手"和"四次挥手"——先确认对方在,再说事,说完确认双方都听清了,再挂断。
三次握手 · 建立连接
TCP 通信前,双方必须先"握手"确认:
① 客户端:SYN
"我想和你建立连接,我的初始序号是 X。"——客户端发一个 SYN 包。
② 服务器:SYN + ACK
"我收到了你的 SYN(确认号 X+1),我也想建立连接,我的初始序号是 Y。"——服务器一次说两件事。
③ 客户端:ACK
"我收到了你的 SYN(确认号 Y+1)。"——三次握手完成,连接建立。
两次行不行?不行——
客户端说"我要连你"(第一次),服务器说"好"(第二次)——但服务器不知道客户端有没有收到它的"好"。如果客户端没收到,服务器就傻等着。
第三次客户端说"我收到了你的好"——服务器才确定"客户端真的在"。
三次之后,双方都确认对方听到了自己。
四次挥手 · 断开连接
说完事要断开,TCP 用"四次挥手":
① 客户端:FIN
"我说完了,准备断开。"
② 服务器:ACK
"我知道你说完了。"——但服务器可能还有数据没发完,所以先确认,不断开。
③ 服务器:FIN
服务器发完剩余数据后,说"我也说完了。"
④ 客户端:ACK
"我知道了。"——客户端等一小会(防止 ACK 丢失),然后彻底断开。
TCP 怎么保证"不丢"
核心机制:序号 + 确认 + 重传。
- 序号每个字节都编一个号——1, 2, 3, 4... 接收方按号排序。
- 确认接收方定期告诉发送方"我收到 1-1000 号了"——叫 ACK。
- 超时重传发送方发现"1001-1500 号"迟迟没收到确认——自动重发。
- 快速重传接收方发现"1001 号没到,但 1002 到了"——立刻告诉发送方"缺 1001",不用等超时。
TCP 怎么保证"不重复"
接收方按序号排序——如果收到重复的号,直接丢弃。就像你收到两封一样的快递,拆一封,另一封扔掉。
TCP 怎么"控速"
网络会堵——TCP 有两个机制防止"把路堵死":
滑动窗口 · Flow Control
接收方告诉发送方"我缓冲区还有多大"——发送方不超过这个量发。
防止"你发太快,我处理不过来"。
拥塞控制 · Congestion Control
TCP 会"试探"网络有多堵——慢慢加速,发现丢包就减速。
防止"大家都猛发,把路堵死"。
滑动窗口 = 你跟副驾说"我胃里还能吃三碗饭"——副驾就最多给你盛三碗。
拥塞控制 = 你上高速先慢慢开,发现不堵就加速,发现刹车灯亮就减速——TCP 也是这么"试探"网络的。
TCP 的"粘包"问题
TCP 是"流式"协议——数据像水一样连续流,没有边界。你发两条消息"Hello"和"World",接收方可能一次收到"HelloWorld"——这叫粘包。
解决办法:应用层自己定边界——比如每条消息前加长度,或用特殊字符分隔(HTTP 用 \r\n\r\n 分隔头部和 body)。
TCP vs UDP · 什么时候用哪个
| 场景 | 用 TCP 还是 UDP | 为什么 |
|---|---|---|
| 网页浏览 | TCP | 网页内容不能错一个字 |
| 文件下载 | TCP | 文件必须完整 |
| 微信文字聊天 | TCP | 消息不能丢 |
| 视频通话 | UDP | 偶尔卡一下没关系,但延迟不能高 |
| 直播 | UDP | 观众容忍花屏,不能容忍延迟 |
| 在线游戏 | UDP 为主 | 位置同步要实时,偶尔丢包无所谓 |
| DNS 查询 | UDP 为主 | 查询简单,一次问答搞定 |
TCP = "靠谱的快递"——三次握手确认身份,序号+确认+重传保证不丢,滑动窗口+拥塞控制防止堵路。
代价是慢一点、复杂一点——所以视频、直播、游戏这些"要快不要全"的场景,会用 UDP(下一篇讲)。