网络编程入门时,知识点看起来很多:TCP、UDP、Socket、阻塞、非阻塞、重传、拥塞控制、并发模型。
如果没有一条主线,很容易学成“术语都见过,但一写程序就还是蒙”。
这篇不打算把协议大全搬一遍,而是想先把网络编程里最常用的几条线捋顺。
1. 网络编程到底在做什么
从很朴素的角度看,网络编程做的事情就是:
- 在不同主机之间传数据
- 处理连接和断开
- 处理发送、接收、超时、重试
但一旦进到真实工程里,它马上会扩展成几个问题:
- 用 TCP 还是 UDP
- 用阻塞还是非阻塞
- 高并发时怎么处理连接
- 性能和稳定性怎么平衡
2. TCP 和 UDP 先怎么区分
这个问题不只是面试题,而是决定代码结构的第一步。
TCP
更适合:
- 需要可靠传输
- 需要顺序
- 需要连接状态
它会帮你处理:
- 重传
- 有序
- 流量控制
- 拥塞控制
UDP
更适合:
- 简单快速
- 对时延更敏感
- 能自己接受丢包或上层处理丢包
所以选型时,重点不是“哪个更高级”,而是业务到底更怕什么:
- 怕丢
- 还是怕慢
3. Socket 在程序里扮演什么角色
Socket 可以先理解成操作系统提供的网络通信接口。
常见流程一般是:
- 创建 socket
- 绑定地址
- 监听或主动连接
- 发送和接收
- 关闭连接
服务端和客户端在细节上不同,但主线差不多。
4. 阻塞和非阻塞为什么会影响整个程序结构
这不是一个小选项,而是会直接影响你怎么组织线程和事件循环。
阻塞式
优点是直观,代码好理解。缺点是一个 I/O 卡住,线程就得等。
非阻塞式
优点是更适合高并发和事件驱动;缺点是代码复杂度会明显上升,需要处理:
- 可读 / 可写事件
- 状态机
- 重试和边界情况
如果连接数不多,阻塞模型可能完全够用;如果连接很多,再继续用“一连接一线程”就可能代价过高。
5. 写网络程序时最容易忽略什么
很多初学者会把 send() 和 recv() 想得过于理想,默认:
- 一次
send()就发完 - 一次
recv()就收完整包
真实情况经常不是这样。
TCP 是字节流,不保证应用层消息边界,所以你要自己处理:
- 粘包
- 拆包
- 半包
如果这层没想清楚,后面协议解析经常一塌糊涂。
6. 高并发连接为什么会把问题放大
连接一多,原本单连接下不明显的问题都会被放大,比如:
- 每连接一个线程导致线程开销过大
- 内存占用持续膨胀
- 锁竞争明显
- 超时和异常处理难以统一
这也是为什么高并发网络服务常见要在下面几类模型里做取舍:
- 多线程
- 多进程
- 事件驱动
- Reactor / Proactor
选型不是为了追时髦,而是要看连接规模、CPU 模型、业务复杂度和团队维护成本。
7. TCP 调优一般都在调什么
很多时候不是“代码错了”,而是默认参数和业务不匹配。
比较常见的调优点包括:
- 发送 / 接收缓冲区
- 超时重传相关参数
- backlog
- keepalive
TCP_NODELAY
其中最容易被频繁提到的就是:
Nagle 算法
它会尽量合并小包,提高带宽利用率,但有时会增加时延。
延迟确认
它和 Nagle 配合不当时,可能把小包交互的时延拉长。
所以如果业务是那种高频小包、强交互场景,经常会考虑是否关闭 Nagle。
8. 嵌入式场景下网络编程有什么额外特点
嵌入式网络编程和服务器开发相比,往往资源更紧,约束更多。
你通常还得额外考虑:
- 内存紧不紧
- 网络栈是不是裁剪版
- 驱动和协议栈交界有没有瓶颈
- 中断和收发路径是否会放大抖动
这意味着很多桌面 / 服务器环境里“理所当然”的做法,在嵌入式上不一定合适。
9. 排查网络问题时更有效的顺序
网络问题通常不要一上来就盯业务代码,先把层次拆开更稳。
先看连接有没有建立
- 三次握手是否正常
- 本地监听和远端地址是否正确
再看收发是否顺畅
- 是否有重传
- 是否有窗口受限
- 是否有明显超时
再看应用层协议
- 是否有粘包拆包问题
- 包头包尾和长度字段是否正确
- 编解码是否一致
这样排会比一开始就猜“是不是协议 bug”更有效。
10. 工程里真正值得积累的经验是什么
如果只积累“某个命令怎么用”,价值有限。更有用的是形成一些固定判断:
- 连接问题先分层
- TCP 稳定性问题别只看应用层
- UDP 丢包问题别默认是代码错
- 高并发问题通常不只是一处函数慢,而是模型不合适
这些判断一旦形成,很多问题会比单纯查资料更快进入正轨。
11. 总结
网络编程最值得先抓住的,不是 API 名字,而是下面几条主线:
- TCP 和 UDP 的取舍
- Socket 的基本收发模型
- 阻塞与非阻塞的结构差异
- 高并发连接的处理方式
- 调优和排障时的分层思路
只要这些线理顺,后面不管你是在写普通客户端、嵌入式网络程序,还是做服务端接入,都会更容易把问题落到正确位置。