1. 网络基础与Socket概述
各位同学,咱们今天正式开讲《Socket编程与网络通信》的第一章。说实话,我每次带新人入门,都会先问一个问题:你知不知道你写的程序,到底是怎么跟另一台机器“说话”的?很多人能写出能跑的代码,但一问到网络分层、IP端口这些基础,就含糊了。嗯,这章咱们就把地基打牢。
1.1 计算机网络分层模型
网络通信这事儿,说白了就是两台设备之间传数据。但这里头涉及的问题太多了——数据怎么拆包?怎么保证不丢?怎么找到对方?如果所有逻辑都揉在一起,谁也写不出来。所以,前辈们想了个办法:分层。
分层的好处很明显:每一层只管自己的事,层与层之间通过标准接口交互。你改了下层实现,上层完全不用动。我在项目里就遇到过,底层从以太网换成Wi-Fi,上层HTTP代码一行没改——这就是分层的威力。
OSI七层模型
OSI模型是国际标准化组织搞出来的理论模型,一共七层。虽然实际落地用的是TCP/IP,但OSI的概念能帮你理解“每一层到底在干嘛”。
| 层级 | 名称 | 核心职责 | 常见协议/设备 |
|---|---|---|---|
| 7 | 应用层 | 为用户应用提供网络服务 | HTTP、FTP、SMTP |
| 6 | 表示层 | 数据格式转换、加密、压缩 | SSL/TLS、JPEG |
| 5 | 会话层 | 建立、管理、终止会话 | NetBIOS、RPC |
| 4 | 传输层 | 端到端可靠传输、流量控制 | TCP、UDP |
| 3 | 网络层 | 路由寻址、分组转发 | IP、ICMP、路由器 |
| 2 | 数据链路层 | 帧封装、介质访问控制 | 以太网、交换机 |
| 1 | 物理层 | 比特流传输、电气信号 | 网线、集线器 |
TCP/IP四层模型
TCP/IP模型是实际工业标准,它把OSI的上三层合并成应用层,下面两层合并成网络接口层。你想想看,互联网上跑的流量,99%都是基于这个模型。
- 应用层:HTTP、DNS、SSH……你平时接触的协议基本都在这一层。
- 传输层:TCP(可靠)和UDP(快速),Socket编程的核心战场。
- 网络层:IP协议,负责把数据包从源主机送到目标主机。
- 网络接口层:物理传输,比如以太网帧。
我个人习惯把TCP/IP模型记成“应传网接”四个字。每次写Socket代码前,我都会在心里过一遍:我这数据从应用层下去,经过传输层加端口信息,网络层加IP头,最后从网卡发出去——反过来收数据也一样。
1.2 IP地址与端口号
网络通信要解决两个核心问题:你在哪 和 找谁。IP地址解决前者,端口号解决后者。
IP地址
IP地址就是网络世界里的门牌号。IPv4是32位,写成四个十进制数,比如 192.168.1.100。IPv6是128位,为了解决地址不够用的问题。
我记得刚入行时,有次配置服务器,把IP写成了 192.168.1.256,结果怎么都连不上。后来一查,IPv4每个段的范围是0-255,256根本不存在。这种低级错误,犯过一次就记住了。
- 127.0.0.1:回环地址,指向本机。你写Socket程序测试时,经常用它。
- 0.0.0.0:监听所有可用网络接口。
- 192.168.x.x / 10.x.x.x / 172.16-31.x.x:私有地址,只在局域网内有效。
端口号
一台机器上跑着几十个网络程序,数据包到了IP地址之后,怎么知道交给哪个程序?端口号就是干这个的。它是一个16位的整数,范围0-65535。
| 端口范围 | 分类 | 举例 |
|---|---|---|
| 0 - 1023 | Well-known(知名端口) | HTTP=80, HTTPS=443, SSH=22 |
| 1024 - 49151 | Registered(注册端口) | MySQL=3306, Redis=6379 |
| 49152 - 65535 | Dynamic/Private(动态/私有) | 客户端临时分配 |
1.3 Socket是什么
说了半天分层和地址,终于到主角了。Socket是什么?说白了,它就是操作系统提供的一个编程接口,让你的程序能够通过网络收发数据。
你可以把Socket想象成一个“网络文件描述符”。你读写文件用 open/read/write/close,网络通信用 socket/connect/send/recv/close——套路几乎一样。实际上,在Unix/Linux系统里,Socket就是一种特殊的文件。
我刚开始学Socket时,总觉得它很神秘。后来想通了:它就是一座桥,一头连着你的应用程序,另一头连着操作系统的网络协议栈。你往桥这头扔数据,协议栈帮你打包、寻址、发送;对端收到后,再从桥那头把数据取出来。
1.4 Socket编程的基本流程
这部分是实操的骨架。不管你是写TCP还是UDP,不管是客户端还是服务端,核心流程都逃不出下面这几步。
TCP Socket 编程流程
TCP是面向连接的、可靠的协议。它的流程就像打电话:先拨号(连接),再通话(收发数据),最后挂断(关闭)。
服务端流程:
- socket():创建Socket,指定协议族(AF_INET)、类型(SOCK_STREAM)、协议(0)。
- bind():绑定IP地址和端口号。不绑定的话,系统会随机分配。
- listen():开始监听,等待客户端连接。参数指定最大等待队列长度。
- accept():阻塞等待,直到有客户端连上来。返回一个新的Socket用于通信。
- recv() / send():收发数据。
- close():关闭连接。
客户端流程:
- socket():创建Socket。
- connect():向服务端发起连接请求,指定IP和端口。
- send() / recv():收发数据。
- close():关闭连接。
// 伪代码示例:TCP服务端核心逻辑
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));
listen(server_fd, 5);
while (1) {
int client_fd = accept(server_fd, NULL, NULL);
// 处理客户端请求...
recv(client_fd, buffer, sizeof(buffer), 0);
send(client_fd, response, strlen(response), 0);
close(client_fd);
}
close(server_fd);
UDP Socket 编程流程
UDP是无连接的,像寄明信片——不保证到达,不保证顺序,但速度快。流程比TCP简单得多。
服务端流程:
- socket():创建Socket,类型用
SOCK_DGRAM。 - bind():绑定地址和端口。
- recvfrom() / sendto():收发数据,每次都要指定对端地址。
- close():关闭。
客户端流程:
- socket():创建Socket。
- sendto() / recvfrom():直接收发,不需要connect。
- close():关闭。
- TCP:面向连接、可靠、有序、有流量控制。适合网页、文件传输、邮件。
- UDP:无连接、不可靠、无序、开销小。适合视频直播、DNS查询、游戏。
嗯,这一章的内容就到这里。网络分层让你知道数据怎么流动,IP和端口让你知道数据去哪找谁,Socket就是那个让你动手操作的把手。后面的章节,我们会一步步把这里的每个步骤拆开,用代码实现出来。