一、Socket基础:网络分层模型、Socket是什么、TCP与UDP的区别、Socket通信流程
各位同学,咱们今天正式开讲。做网络编程这么多年,我见过太多人一上来就撸Socket代码,结果连数据是怎么从A机器跑到B机器的都说不清楚。说实话,这样写出来的程序,线上不出问题才怪。
所以第一章,咱们先把地基打牢。你想想看,盖楼不打地基,早晚得塌。网络编程也一样。
1.1 网络分层模型:数据是怎么「飞」过去的?
先问大家一个问题:你在浏览器里输入一个网址,回车之后,数据到底经历了什么?
答案就在网络分层模型里。目前主流的有两套:OSI七层模型和TCP/IP四层模型。OSI是理论上的「完美标准」,但实际互联网用的是TCP/IP模型。我个人的习惯是,把两者结合起来理解,但写代码时只认TCP/IP。
| OSI七层模型 | TCP/IP四层模型 | 典型协议/设备 | 一句话理解 |
|---|---|---|---|
| 应用层 | 应用层 | HTTP, FTP, DNS | 你直接打交道的东西 |
| 表示层 | SSL/TLS, JPEG | 数据格式翻译、加密 | |
| 会话层 | NetBIOS, RPC | 建立/管理会话 | |
| 传输层 | 传输层 | TCP, UDP | 端到端传输,核心战场 |
| 网络层 | 网络层 | IP, ICMP, 路由器 | 寻址和路由选择 |
| 数据链路层 | 网络接口层 | 以太网, MAC地址, 交换机 | 相邻节点传输 |
| 物理层 | 网线, 光纤, 集线器 | 比特流在介质上传输 |
数据发送时,是从上往下层层「打包」——每一层加上自己的头部信息。接收时,从下往上层层「拆包」。这个过程叫封装与解封装。
核心概念: 每一层只关心自己的职责,下层为上层提供服务。这就是「分层」的精髓——各司其职,解耦。
下面这张图,是我自己画的数据封装流程,你一看就明白。
1.2 Socket到底是什么?别把它想得太玄乎
很多初学者觉得Socket是个很高深的东西。其实说白了,Socket就是操作系统提供的一个编程接口,让你能通过文件描述符的方式,操作网络数据收发。
嗯,这里要注意:Socket本身不是协议,它只是对TCP/IP协议栈的一层封装。你调用的send()、recv(),底层走的还是TCP或UDP。
一句话总结: Socket = IP地址 + 端口号 + 协议类型。它是网络通信的「门把手」,你握住它,就能跟另一台机器上的程序对话。
我记得刚入行那会儿,有个同事把Socket理解成「一条管道」,总觉得数据发出去就一定能到。后来线上出了丢包问题,他才明白Socket只是接口,可靠性得靠协议本身保证。
1.3 TCP与UDP的区别:选错协议,线上哭都来不及
这是面试高频题,也是实际选型最容易踩坑的地方。我直接给你上对比表,一目了然。
| 对比维度 | TCP | UDP |
|---|---|---|
| 连接状态 | 面向连接(先握手,再通信) | 无连接(直接发,不打招呼) |
| 可靠性 | 可靠传输(有确认、重传机制) | 不可靠(发出去就不管了) |
| 数据顺序 | 保证数据按序到达 | 不保证顺序 |
| 传输方式 | 字节流(无边界) | 数据报(有边界,一次一个报文) |
| 速度 | 相对较慢(有开销) | 快(无握手、无确认) |
| 典型应用 | HTTP, FTP, SSH, 数据库连接 | DNS, 视频直播, 在线游戏, VoIP |
为什么会这样?TCP有三次握手、四次挥手、滑动窗口、拥塞控制……这些机制保证了可靠性,但也带来了延迟。UDP呢?什么都不管,闷头就发,所以快,但数据可能半路就没了。
你想想看,视频通话丢一帧画面,你眨个眼就过去了。但银行转账丢一条记录,那可就出大事了。这就是选型的关键。
1.4 Socket通信流程:从创建到关闭,一个完整的生命周期
这部分是写代码的基础。我习惯把Socket通信分成三个角色:服务端、客户端、以及它们之间的「对话」。
先看服务端,它是个「被动方」,一直等着别人来找它。
- 创建Socket:
socket(),指定协议族和类型。 - 绑定地址和端口:
bind(),把Socket和本地的IP、端口绑在一起。 - 监听:
listen(),告诉内核:「我准备好了,有人连我就通知你」。 - 接受连接:
accept(),阻塞等待,直到有客户端连上来。 - 收发数据:
recv()/send(),开始通信。 - 关闭连接:
close(),释放资源。
客户端就简单多了,它是「主动方」。
- 创建Socket:
socket()。 - 连接服务端:
connect(),指定服务端的IP和端口。 - 收发数据:
send()/recv()。 - 关闭连接:
close()。
下面这张流程图,把整个过程串起来了。
下面是一个最简的Python示例,演示了TCP服务端和客户端的基本骨架。
# tcp_server.py - 服务端
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 8888))
server_socket.listen(5)
print('服务端已启动,等待连接...')
client_socket, client_addr = server_socket.accept()
print(f'客户端 {client_addr} 已连接')
data = client_socket.recv(1024)
print(f'收到: {data.decode()}')
client_socket.send(b'Hello, Client!')
client_socket.close()
server_socket.close()
# tcp_client.py - 客户端
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('127.0.0.1', 8888))
client_socket.send(b'Hello, Server!')
data = client_socket.recv(1024)
print(f'收到: {data.decode()}')
client_socket.close()
好了,第一章的内容就到这里。网络分层模型让你知道数据怎么走,Socket让你知道怎么操作,TCP/UDP让你知道怎么选,通信流程让你知道怎么写代码。这四块拼在一起,就是Socket编程的完整地基。