1. 网络编程基础概念
说实话,每次带新人入门网络编程,我都会先问一个问题:「你知不知道,当你打开浏览器输入网址,背后到底发生了什么?」
这个问题看似简单,但能完整答上来的人真不多。我自己刚入行那会儿,也是一知半解。直到有一次线上服务出了故障,排查了半天才发现是网络分层理解不到位导致的——嗯,从那以后,我就老老实实把基础补上了。
今天这一章,咱们就把网络编程最核心的几个概念捋清楚。别急,我会用我踩过的坑帮你避开弯路。
1.1 OSI七层模型——理论上的「完美蓝图」
OSI七层模型,说白了就是国际标准化组织(ISO)给网络通信画的一张「设计图」。它把通信过程拆成了七层,每一层只管自己的事。
| 层级 | 名称 | 核心作用 | 我常联想到的 |
|---|---|---|---|
| 7 | 应用层 | 为用户提供网络服务(HTTP、FTP) | 你用的浏览器、 |
| 6 | 表示层 | 数据格式转换、加密解密 | 压缩、编码 |
| 5 | 会话层 | 建立、管理、终止会话 | 登录状态的保持 |
| 4 | 传输层 | 端到端可靠传输(TCP/UDP) | 快递的「送货上门」 |
| 3 | 网络层 | 路由选择、IP寻址 | 快递的「分拣中心」 |
| 2 | 数据链路层 | 帧封装、MAC地址寻址 | 同一小区内的配送 |
| 1 | 物理层 | 比特流传输(网线、光纤) | 快递的「运输车辆」 |
你可能会问:「七层这么多,实际用得到吗?」
说实话,日常开发中我们接触最多的是应用层、传输层和网络层。但理解七层模型有个好处——排查问题时,你能快速定位是哪一层出了岔子。我曾经遇到一个诡异的问题:应用层日志显示发送成功,但对方就是收不到。后来发现是传输层的TCP窗口满了,数据被阻塞了。你看,不懂分层,你连问题在哪都找不到。
1.2 TCP/IP四层模型——实际工业标准
OSI七层模型虽然完美,但太复杂了。实际互联网用的是TCP/IP四层模型,它把七层压缩成了四层:
- 应用层:对应OSI的应用层、表示层、会话层。HTTP、FTP、SMTP都在这里。
- 传输层:对应OSI的传输层。TCP和UDP是主角。
- 网络层:对应OSI的网络层。IP协议在这里干活。
- 网络接口层:对应OSI的数据链路层和物理层。网卡驱动、硬件都在这一层。
我个人习惯把TCP/IP模型叫做「实战派」。为什么?因为你在写网络程序时,打交道最多的就是这四层。比如你用Socket编程,本质上就是在应用层和传输层之间搭桥。
核心要点:OSI是理论,TCP/IP是实践。面试时两者都要懂,但写代码时按TCP/IP来。
1.3 IP地址与端口号——网络世界的「门牌号」
想象一下,你要给朋友寄快递。你需要两个信息:
- IP地址:相当于「小区地址」,找到对方的主机。
- 端口号:相当于「房间号」,找到主机上的具体程序。
IP地址分两种:
- IPv4:32位,像 192.168.1.1。总共约43亿个地址,现在快用完了。
- IPv6:128位,像 2001:0db8:85a3::8a2e:0370:7334。地址多到给地球上每粒沙子都能分配一个。
端口号的范围是0~65535,其中:
- 0~1023:知名端口,比如HTTP用80,HTTPS用443,SSH用22。
- 1024~49151:注册端口,给应用程序用。
- 49152~65535:动态/私有端口,客户端临时使用。
避坑指南:我曾经在项目里把服务端口设成了8080,结果和另一个服务冲突了。后来我养成了习惯——写代码前先查端口占用。用 netstat -an | grep 端口号 看一眼,省得后面出幺蛾子。
1.4 Socket概念——网络编程的「入口」
Socket,中文叫「套接字」。说白了,它就是操作系统提供的一个编程接口,让你能通过代码收发网络数据。
我刚开始学Socket时,觉得它很神秘。后来发现,它本质上就是一个文件描述符。你读写Socket,就像读写文件一样——只不过数据是在网络上传输而已。
一个典型的TCP Socket通信流程是这样的:
// 服务端
int server_fd = socket(AF_INET, SOCK_STREAM, 0); // 创建Socket
bind(server_fd, &addr, sizeof(addr)); // 绑定IP和端口
listen(server_fd, 5); // 监听连接
int client_fd = accept(server_fd, NULL, NULL); // 接受客户端连接
read(client_fd, buffer, sizeof(buffer)); // 读取数据
write(client_fd, "Hello", 5); // 发送数据
close(client_fd); // 关闭连接
// 客户端
int sock = socket(AF_INET, SOCK_STREAM, 0); // 创建Socket
connect(sock, &addr, sizeof(addr)); // 连接服务端
write(sock, "Hi", 2); // 发送数据
read(sock, buffer, sizeof(buffer)); // 接收数据
close(sock); // 关闭连接
你看,代码其实不长。但这里有个坑——很多人忘了处理错误返回值。我见过一个线上事故,就是因为 accept() 返回了-1,但代码没检查,直接拿-1去读写,结果程序崩溃了。所以我的习惯是:每个系统调用都要检查返回值,哪怕你觉得「不可能出错」。
1.5 知识体系总览
为了让你更直观地理解这些概念之间的关系,我画了一张图:
这张图把OSI七层、TCP/IP四层和核心编程概念串在了一起。你从左往右看,就能明白:理论模型最终落地到IP、端口、Socket这些具体概念上。
1.6 小结
这一章我们聊了:
- OSI七层模型——理论框架,帮你理解网络分层思想
- TCP/IP四层模型——实际标准,写代码时按这个来
- IP地址和端口号——定位主机和程序的「门牌号」
- Socket——网络编程的入口,本质是文件描述符
说实话,这些概念刚接触时可能觉得抽象。但别急,后面几章我们会用代码把这些概念一个个「敲」出来。到时候你会发现——原来网络编程,不过如此。
注意:本章所有代码示例都是简化版,实际生产环境需要处理更多边界情况。比如 bind() 之前要设置 SO_REUSEADDR 选项,否则重启服务时会报「Address already in use」。这个坑我踩过不止一次,你记住了。