第一章:网络编程基础回顾

大家好,我是你们的老朋友。做网络编程优化这么多年,我见过太多人一上来就追求高大上的框架,结果连最基础的Socket模型都搞不清楚。说实话,这就像盖楼不打地基——早晚要塌。今天咱们就把这块地基夯实了。

1.1 Socket编程模型:从零开始

Socket,中文叫套接字,说白了就是操作系统提供的一个通信接口。你想想看,两台机器要聊天,总得有个门吧?Socket就是这个门。

我个人习惯把Socket编程分成三步走:

  1. 创建Socket——开门
  2. 绑定/连接——确定跟谁聊
  3. 收发数据——开始聊天

来看一个最简单的TCP服务端代码:

import socket

# 创建Socket
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定地址和端口
server_sock.bind(('0.0.0.0', 8888))

# 开始监听
server_sock.listen(5)

print('服务端已启动,等待连接...')

while True:
    # 接受客户端连接
    client_sock, addr = server_sock.accept()
    print(f'收到来自 {addr} 的连接')
    
    # 接收数据
    data = client_sock.recv(1024)
    print(f'收到数据: {data.decode()}')
    
    # 发送响应
    client_sock.send(b'Hello, Client!')
    
    # 关闭连接
    client_sock.close()

这段代码看着简单,但我得提醒你——它只能同时处理一个客户端。为什么?因为accept()和recv()都是阻塞的。我在项目中遇到过,有人拿这个代码去生产环境,结果第二个用户一来就卡死了。嗯,这里要注意。

1.2 TCP vs UDP:选谁更合适?

很多新手问我:「TCP和UDP到底选哪个?」我的回答是:看场景。

特性 TCP UDP
连接方式 面向连接(先握手) 无连接(直接发)
可靠性 可靠(有重传机制) 不可靠(丢了就丢了)
数据顺序 保证顺序 不保证顺序
传输速度 相对慢 快
典型应用 HTTP、FTP、邮件 视频直播、DNS、游戏

我曾经帮一个直播平台做优化,他们一开始用的TCP,结果卡顿严重。我建议换成UDP,配合应用层的丢包补偿,延迟直接降了60%。说白了,TCP的可靠性是用延迟换来的,如果你能接受偶尔丢包,UDP就是更好的选择。

核心原则:需要数据完整性的用TCP,追求实时性的用UDP。

1.3 阻塞与非阻塞IO:别再傻等了

阻塞IO,就是程序在那干等着。比如你调用recv(),如果对方没发数据,你的程序就卡在那了。非阻塞IO呢?它会立刻返回一个错误,告诉你「没数据,你先干别的去」。

来看对比代码:

import socket

# 阻塞模式(默认)
sock = socket.socket()
sock.setblocking(True)  # 这行不写也行,默认就是阻塞
data = sock.recv(1024)  # 没数据?等着!

# 非阻塞模式
sock = socket.socket()
sock.setblocking(False)
try:
    data = sock.recv(1024)  # 没数据?立刻抛异常
except BlockingIOError:
    print('没数据,我先干点别的')

你想想看,如果服务端用阻塞模式,一个recv()就把线程卡死了。那怎么处理多个客户端?传统做法是来一个客户端就开一个线程。但线程多了,上下文切换的开销也大。

我的建议:小项目用多线程阻塞IO就够了,简单好维护。高并发场景,用非阻塞IO配合事件循环(比如select、epoll),这才是高性能的基石。

我曾经接手过一个老项目,每个连接开一个线程,同时在线5000人时服务器直接崩了。改成非阻塞IO + epoll后,同样的机器扛到了5万连接。嗯,差距就是这么大。

避坑指南:非阻塞IO的recv()会频繁返回EAGAIN错误,如果你在循环里不停地调用它,CPU会被吃满。一定要配合select/poll/epoll来用,让操作系统告诉你「什么时候数据准备好了」。

知识体系总览

下面这张图,是我自己总结的网络编程基础知识框架。你看一眼,心里就有谱了。

网络编程基础知识体系 Socket编程模型 TCP vs UDP 阻塞与非阻塞IO 创建 → 绑定 → 监听 → 连接 收发数据:send() / recv() 关闭连接:close() TCP:可靠、有序、面向连接 UDP:不可靠、无序、无连接 选型:完整性 vs 实时性 阻塞:简单但效率低 非阻塞:高效但复杂 配合select/epoll使用 核心思想:理解底层原理,才能写出高性能网络程序 不要盲目追求框架,基础不牢地动山摇

好了,这一章的内容就这些。Socket模型是骨架,TCP/UDP是血肉,阻塞与非阻塞是灵魂。这三样搞明白了,后面的性能优化才有得谈。

可可精品资料库