TCP 协议 - 网络世界的"靠谱快递员" 📦
date
Nov 14, 2025
slug
nodejs-tcp
status
Published
tags
Node.js
summary
嘿各位!今天咱们聊聊 TCP(传输控制协议),这个让网络通信变得靠谱的幕后英雄。
type
Post
TCP 是什么?先打个比方 📬
想象你要给朋友寄一本书,有两种快递可选:
普通快递(IP协议):
- 把书撕成100页,每页单独寄
- 可能乱序到达(第50页先到,第1页后到)
- 可能丢几页
- 便宜但不靠谱 😅
靠谱快递(TCP协议):
- 保证每一页都到
- 保证按顺序到(1、2、3...100)
- 丢了会重发
- 有点慢但放心
TCP 就是网络世界的"靠谱快递员"!
TCP 的核心特性:为啥它这么靠谱?🛡️
1. 面向连接(Connection-Oriented)
TCP 不是"扔了就走",而是建立连接、维护连接、关闭连接。
就像打电话:先拨号接通,然后聊天,最后说拜拜挂断 ☎️
而底层的 IP 协议是面向数据报的,每个数据包独立传输,互不相关。
IP 更像发短信:一条一条发,不管对方收没收到,也不管顺序
2. 保证顺序传递
你发送:"我爱Node.js"
TCP 保证对方收到的也是:"我爱Node.js"
而不是:"js我爱Node." 😱
怎么做到的?
每个 IP 数据包都包含:
- 连接标识符
- 数据流顺序信息
假设一条消息分成 4 部分,服务器收到第 1 和第 4 部分后,会等待第 2 和第 3 部分。
就像拼图,缺了中间几块,会等齐了再拼完整 🧩
3. 面向字节(Byte-Oriented)
TCP 完全不关心你发的是什么字符、什么编码。
- ASCII:每个字符 1 字节
- Unicode:每个字符 4 字节
都可以!TCP 只管传字节流。
就像快递员不管你箱子里装的是书还是衣服,只管送 📦
这种灵活性让 TCP 适用性极强。
4. 可靠性(Reliability)
TCP 基于确认和超时机制:
- 发送数据
- 等待确认消息(ACK)
- 如果超时未收到 → 重发
就像你发完微信,看到对方"已读"才放心。没"已读"?再发一遍! ✅
5. 流控制(Flow Control)
两台电脑速度差异很大怎么办?
TCP 会确保快的不会压垮慢的。
就像你倒水,杯子快满了就慢点倒,不会一股脑全倒进去溅出来 🚰
6. 拥塞控制(Congestion Control)
TCP 会控制传输速率,避免网络拥堵。
就像高速公路堵车时,大家都开慢点,避免更堵 🚗
Telnet:测试 TCP 的神器 🔧
Telnet 是个早期网络协议,现在主要用来测试 TCP 连接。
虽然因为安全问题已经被 SSH 取代,但绝大部分操作系统都内置了 telnet 客户端。
有趣的特性
Telnet 发现服务器不是 Telnet 协议时,不会报错或断开,而是自动降级到纯 TCP 模式。
这让我们可以用它测试任何 TCP 服务!
实验:用 Telnet 访问 HTTP 服务器
先写个简单的 HTTP 服务器:
运行:
node web-server.js然后用 Telnet 连接:
连接成功!但没看到 "Hello World",为什么?
因为还没发 HTTP 请求!在终端输入:
Boom! 服务器响应出现了:
我们做了什么?
- ✅ 建立 TCP 连接
- ✅ 创建 HTTP 请求
- ✅ 接收 HTTP 响应
- ✅ 验证了 TCP 特性(数据按序到达)
实战项目:基于 TCP 的聊天程序 💬
理论讲够了,咱们撸代码!
项目需求
做个简单的聊天服务器:
- 连接后显示欢迎语和当前在线人数
- 输入用户名
- 可以向其他用户发送消息
为什么按回车键?
Telnet 会立即发送你输入的每个字符。按回车是为了发送
\\n 字符,作为消息分隔符。就像发微信,按发送键才真正发出去 📱
第一步:创建项目
第二步:理解 net.Server API
运行:
node index.js用 Telnet 连接:
telnet 127.0.0.1 3000成功!控制台显示 "new connection!"
核心概念
createServer的回调会在每次新连接时执行
- 回调接收一个 Stream 对象(既可读又可写)
listen是异步的,可以传回调函数
http.Server 其实继承自 net.Server,现在理解"HTTP 建立在 TCP 之上"了吧? 🏗️
第三步:接收连接并发送欢迎语
添加计数器:
重启服务器,用 Telnet 连接,看到欢迎语了!
第二个客户端连接时,计数器显示 1!
第四步:处理断开连接
为什么用
close 而不是 end?end:客户端正常关闭连接时触发
close:任何情况下连接关闭都触发(包括错误)
更稳妥的选择! 🛡️
第五步:监听 data 事件
在客户端输入 "hi",服务器控制台输出:
收到的是 Buffer!因为 TCP 是面向字节的。
设置编码
不想每次都转换?设置编码:
现在输出的就是字符串了!
第六步:状态管理和用户验证
引入
users 对象追踪所有连接:每个连接保存昵称:
现在新用户加入时,所有人都能看到通知!
第七步:发送聊天消息
两个客户端可以聊天了!🎉
第八步:圆满完成
抽象广播函数:
简化代码:
完成! 一个功能完整的聊天服务器 ✨
进阶:IRC 客户端 🤖
前面写了服务器,现在写个客户端。
IRC(Internet Relay Chat)是基于 TCP 的聊天协议。
理解 net.connect API
连接到服务器:
实现部分 IRC 协议
连接到
irc.freenode.net 的 #node.js 频道:注意:IRC 命令以
\\r\\n 结尾(就像 HTTP 头一样)。运行后,你的 IRC 客户端就连上真实的 IRC 服务器了!
作为练习
你可以尝试:
- 解析接收到的
data,提取聊天消息
- 实现一个 IRC 机器人,自动回复命令
- 当有人说 "date" 时,回复当前时间
小结 📝
这一章我们:
✅ 理解了 TCP 的核心特性(连接、顺序、可靠性)
✅ 用 Telnet 测试了 TCP 服务
✅ 用 Node.js 写了一个聊天服务器
✅ 实现了一个 IRC 客户端
关键知识点
TCP 特性:
- 面向连接(建立、维护、关闭)
- 保证顺序(数据按序到达)
- 面向字节(不关心编码)
- 可靠性(确认 + 重传)
- 流控制(快的等慢的)
- 拥塞控制(避免网络堵塞)
Node.js API:
net.createServer():创建 TCP 服务器
net.connect():创建 TCP 客户端
conn.setEncoding():设置编码
conn.write():发送数据
- 事件:
connect、data、close、error
重要概念
共享状态的并发:多个连接修改同一个变量(
count、users)Stream:既可读又可写的对象
分隔符:
\\r\\n 用于区分消息边界下一步 🚀
现在你对 TCP 中的数据传递、数据块构建已经很清楚了,下一章我们会学习 HTTP——TCP 上层的协议。
到时候你会发现,理解了底层的 TCP,学习 HTTP 会轻松很多!
就像你学会了骑自行车,学摩托车就容易了 🏍️
好了,今天的分享就到这里!现在你已经掌握了网络编程的基础,可以构建各种实时通信应用了 💪
记住:HTTP、WebSocket、数据库连接...很多东西都基于 TCP。掌握了 TCP,你就掌握了网络编程的根基!
有问题欢迎留言,咱们下次见!📡✨
彩蛋:常见问题 🤔
Q: TCP 和 UDP 有什么区别?
A: TCP 是"靠谱快递"(保证送达、保证顺序),UDP 是"扔了就走"(快但不保证)。游戏、视频通话常用 UDP,网页、文件传输用 TCP。
Q: 为什么 HTTP 基于 TCP?
A: 因为网页需要完整传输。少一个字节,页面可能就坏了。TCP 的可靠性正好符合需求。
Q: close 和 end 有什么区别?
A:
end 是正常关闭,close 包括所有关闭情况(正常+异常)。生产环境推荐用 close。Q: 为什么要 setEncoding?
A: 因为 TCP 传输的是字节流(Buffer),设置编码后自动转成字符串,省得每次手动转换。
继续加油!🔥