如何使用Python搭建支持跨公网访问的Pygame非本地游戏服务器
Pygame本地服务端改造为公网可访问方案
现有代码基础问题排查
先修复几个会直接影响运行、阻断公网连接的显性问题:
server.py和network.py都缺失socket模块导入,两个文件开头都要加import socket;Linux/macOS系统下文件名大小写敏感,client.py里的from Network import Network要和实际文件名network.py匹配,否则会报导入错误- 服务端原绑定逻辑是绑定本机自动获取的内网IP,只能接收同局域网请求,无法接收公网卡转发过来的流量
- 客户端原网络逻辑是自动读取本机IP当服务端地址,跨网访问时根本连不到远端服务器
改造步骤
1. 修改服务端绑定地址
服务端不要绑定特定内网IP,改为绑定0.0.0.0,这个地址代表监听本机所有网卡的入站请求,不管是内网、本地回环还是公网转发过来的请求都能正常接收。
把server.py里初始化部分的绑定逻辑改成如下:
# 删除原 ip = (socket.gethostbyname(socket.gethostname())) 代码 ip = "0.0.0.0" port = 5555 self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 新增端口复用配置,避免服务端频繁重启时报端口被占用错误 self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: self.s.bind((ip, port)) except socket.error as e: print(e) print(f"服务端已启动,监听{port}端口所有网卡请求")
2. 打通公网访问链路
根据你部署服务端的网络环境选对应配置:
- 如果你用云服务器部署(自带公网IP的云主机):
- 去云服务商控制台的安全组配置,添加入站规则,放行TCP协议5555端口,允许所有来源IP访问
- 登录服务器系统,放开系统防火墙对TCP 5555端口的限制:Windows系统就在防火墙高级设置里添加允许入站规则,Linux系统如果开了ufw/firewalld就添加对应端口放行规则
- 这台服务器的公网IP就是客户端要填写的连接地址
- 如果你把服务端部署在家庭/公司内网,没有独立公网IP:
- 优先联系宽带运营商申请动态公网IP,目前国内大部分地区电信、联通家宽都可以免费申请,拿到公网IP后进路由器管理后台,配置端口映射/虚拟服务器规则:把路由器公网IP的TCP 5555端口,转发到你运行服务端的那台内网设备的内网IP(比如192.168.3.12)的5555端口上
- 如果拿不到公网IP,可以用内网穿透工具,将本地5555端口映射到公网可访问的地址和端口,映射得到的公网地址就是客户端的连接地址
3. 修改客户端连接逻辑
原来的network.py自动读取本机IP当服务端地址的逻辑只适合本地/同局域网测试,跨网访问时要把服务端地址改成你上一步拿到的公网地址。
修改network.py的初始化部分:
import socket import pickle class Network: def __init__(self, server_ip): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 如果做端口映射/穿透时改了端口,这里对应修改 self.port = 5555 self.addr = (server_ip, self.port) self.p = self.connect() def connect(self): self.sock.connect(self.addr) p = pickle.loads(self.sock.recv(2048)) return p def send(self, data): self.sock.sendall(pickle.dumps(data)) # 注意:固定recv(2048)在网络波动时可能出现收不全/粘包问题,demo测试够用,正式上线要加长度前缀处理TCP流边界 return pickle.loads(self.sock.recv(2048))
对应client.py里初始化Network的位置,传入服务端公网IP即可:
# 替换原 n = Network() 代码,把引号里的内容换成你实际的服务端公网地址 n = Network("你的服务端公网IP")
测试验证
- 先在服务端机器上启动
server.py,确认没有端口绑定报错 - 用手机开热点给测试电脑(确保测试电脑和服务端不在同一个局域网),启动客户端,验证是否能正常连接、同步玩家位置
- 如果连不上,逐段排查:先查服务端防火墙/安全组有没有放开端口,再查端口映射/穿透配置有没有生效,最后确认客户端填的公网地址和端口正确
注意:用pickle做网络序列化有安全风险,不要让不可信的客户端连接你的服务端,避免恶意构造的pickle数据在服务端执行任意代码。demo测试没问题,正式上线建议换成JSON/Protobuf等安全的序列化格式。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

