以前你的 Python 程序都是自己跑自己的,像孤岛。今天,我们要让两台电脑上的程序互相发消息——这就是网络编程。
而且,为了让服务器能同时服务多个客户,我们还会引入“多进程”,就像开了好几个窗口同时接单。


一、先搞清三个最基本的概念:IP、端口、协议

想象你要给住在另一个城市的朋友写信:

  • IP 地址 = 朋友的小区地址(比如“幸福里小区3号楼”)。它帮你把信送到正确的那栋楼。

  • 端口号 = 朋友家的门牌号(比如“203室”)。同一栋楼里有好多户,端口号告诉送信的人:“这封信是给 203 室的张三的”。

  • 协议 = 你们俩约定好用中文写信,而不是英文或者火星文。协议规定了数据怎么包装、怎么确认收到、丢了怎么办。

所以网络编程的核心就是:用 IP 找到那台电脑,用端口找到那个程序,用协议保证两边能听懂

小贴士

  • 本机测试时,IP 可以用 127.0.0.1,意思是“我自己”。就像给自己打电话。

  • 端口号一般用 1024 以上的数字(比如 8000、9000),因为低端口经常被系统程序占着。


二、TCP 协议:像打电话一样可靠

TCP 是互联网上最常用的协议之一,它的三大特点你一定要记住:

  1. 面向连接:正式说话之前,必须先“拨通电话”,双方确认对方在线。不像发短信(UDP),扔出去就不管了。

  2. 可靠传输:你发的每一个字节,对方都会确认收到。如果中途丢了,会自动重传,最后保证顺序不乱。适合网页、文件下载、聊天。

  3. 面向字节流:数据像流水一样连续发送,没有天然的“消息边界”。好比你把一桶水倒进管道,对方接到的是连续的水,你得自己想办法分成一杯一杯(比如加换行符、固定长度)。

1. 三次握手:怎么“拨通电话”的?

建立 TCP 连接时,双方要在底层交换三个小包,俗称三次握手。你可以想象成:

  • 客户端:“喂,能听见吗?我想跟你说话。”(发 SYN)

  • 服务器:“听见了,我也能听见你。你说吧。”(发 SYN+ACK)

  • 客户端:“好的,那开始说正事。”(发 ACK)

为什么不是两次?
如果只有两次,服务器发出“听见了”之后,无法确认客户端是否真的准备好了。万一客户端的请求是重复的旧请求,服务器就直接连上了,可能浪费资源。三次握手能保证双方都同意、并且交换了初始序号,是最小的可靠方案。

2. 四次挥手:怎么“挂电话”的?

TCP 连接是全双工的,就是两边都能同时说话、同时听。所以关闭的时候,要分别关闭两个方向:

  • 主动方:“我说完了,我要挂掉我这边的发送。”(发 FIN)

  • 被动方:“好的,我知道你说完了。”(回 ACK)
    此时被动方可能还有话没说完,所以它继续发。

  • 被动方:“我也说完了,我要挂掉我这边的发送。”(发 FIN)

  • 主动方:“好的,知道你挂了。”(回 ACK)
    然后等一小会儿(TIME_WAIT),确保对方收到了最后的确认,才彻底关闭。

为什么不是三次?
因为被动方收到“我说完了”时,不一定立刻就能结束(可能还在发数据),所以不能把第二步和第三步合并。只有等它自己也发完了,才能单独发 FIN。这就成了四次。

你不需要背太深,但要知道:建立连接三次,断开连接四次,这是 TCP 的经典规矩。


三、Socket 是什么?一个“网络电话机”

操作系统提供了一个叫 Socket(套接字) 的东西,它就像一部电话机。你写 Python 程序,不需要自己处理网线、电信号,只需要:

  • 买一部电话机(创建 socket 对象)

  • 拨号或接听(connect、bind、listen、accept)

  • 说话(send)

  • 听对方说话(recv)

  • 挂机(close)

我们来看服务端和客户端分别怎么“用电话”。


四、服务端:开一个“客服热线”

服务端程序要被动等待别人打进来。步骤依次是:

  1. 买电话机:创建一个 TCP socket。

  2. 插电话线:绑定一个 IP 和端口(bind),告诉系统“我要在这个地址接电话”。如果 IP 写 0.0.0.0,表示监听本机所有网卡;写 127.0.0.1 就只能本机自己打给自己。

  3. 设置成待机状态:调用 listen,告诉系统“可以有人排队了”。

  4. 接听一个来电:调用 accept,程序会卡住(阻塞),直到真的有客户端连上来。然后它会返回一个新的电话机(新的 socket),专门用于和这个客户聊天,而原来的电话机继续等下一个客户。

  5. 聊几句:用新 socket 的 recv 接收对方的话(字节流,需要用 decode 转成字符串),用 send 发送回复(需要 encode)。

  6. 挂断这个客户的电话close 这个新 socket。如果还想服务下一个客户,就回到第 4 步继续 accept

注意:accept 和 recv 都是阻塞的,意思是程序会停在那行,直到有事件发生。这就引出了多任务的需求——如果服务端只用一个循环,一次只能服务一个客户,其他人得排队。


五、客户端:主动打电话的人

客户端就简单多了:

  1. 买电话机(创建 socket)。

  2. 拨号connect((服务器 IP, 端口)),阻塞直到接通。底层会完成三次握手。

  3. 说话/听话send 和 recv(和服务器端一样)。

  4. 挂机close

客户端没有 bindlistenaccept,因为它是主动方。


六、顺便说一下:字符串和字节的转换

网络传输只认字节(bytes),不认字符串。所以:

  • 发的时候:"你好".encode('utf-8') 变成字节串。

  • 收的时候:收到的字节用 decode('utf-8') 变回字符串。

两边的编码必须一致,一般都用 UTF-8。


七、多进程:让服务器能同时服务好几个人

刚才说了,如果服务端只有一个循环,那么一次只能跟一个客户聊天,其他人排队。这显然不实用。

解决办法是:当 accept 接到一个客户后,立刻创建一个子进程,让子进程去跟这个客户聊天,主进程继续回来 accept 等待下一个客户。这样就能“同时”服务很多人了。

1. 什么是进程?

进程就是程序的一次运行实例。你打开一个微信,操作系统就给微信分配一个进程。进程之间是隔离的,内存不共享(后面会讲到)。

2. 怎么创建子进程(Python 的 multiprocessing

import multiprocessing

def 聊天(新socket, 客户地址):
    # 这里写 recv/send 的循环
    pass

if __name__ == '__main__':
    监听socket = 创建并bind、listen...
    while True:
        新socket, 地址 = 监听socket.accept()
        p = multiprocessing.Process(target=聊天, args=(新socket, 地址))
        p.start()   # 启动子进程
        # 主进程继续回去 accept

重点

  • target 后面写函数名,不要加括号。

  • 如果子进程要传参数,用 args=(参数1, 参数2),注意只有一个参数时也要写成 (参数,) 加个逗号。

  • 在 Windows 上,创建进程的代码必须放在 if __name__ == '__main__': 里面,否则会出错。

3. 进程 ID(PID)

每个进程都有一个编号,叫 PID。你可以用 os.getpid() 获取当前进程的 PID,os.getppid() 获取父进程的 PID。这对调试多任务很有用。

4. 进程之间默认不共享全局变量

这一点很重要:两个进程各自拥有一份全局变量的拷贝,你在子进程里修改了一个列表,主进程里看不到变化。因为它们的内存是独立的。如果非要共享,需要用队列、管道等专门工具(以后会学)。


八、一个小坑:端口被占用怎么办?

当你把服务器程序关掉后立刻重启,有时候会报“地址已被占用”。这是因为操作系统要等一会儿(TIME_WAIT 状态)才能释放端口。解决办法是在 bind 之前设置端口重用:

socket对象.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

记住:必须在 bind 之前,否则没用。


九、文件上传的思路(其实就是聊天模式的变种)

  • 客户端:打开文件(二进制模式),循环读取一小块(比如 1024 字节),用 send 发出去。发完关闭连接。

  • 服务端:接受连接后,以二进制写模式打开一个新文件,循环 recv 一小块,直接写入文件。当 recv 返回空字节(b'')时,表示客户端关闭了连接,上传完成。

为什么要分块?因为文件可能很大,一次性读入内存太浪费,网络也是流式的,边读边发更合理。


十、总结

概念 一句话解释
IP 找到哪台电脑
端口 找到电脑上的哪个程序
TCP 面向连接、可靠、字节流(像打电话)
三次握手 建立连接时互相确认
四次挥手 关闭连接时分方向关闭
Socket 编程用的“网络电话机”
服务端流程 创建→绑定→监听→accept→recv/send→close
客户端流程 创建→connect→send/recv→close
进程 程序的一次运行实例
多进程 用子进程同时处理多个客户端
全局变量 默认不共享

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐