本文记录了使用 AI 开发环境与大语言模型,在 24 小时内完成 Python 版 iptux(飞鸽传书兼容)复刻的全过程。
本项目已开源,仓库地址:https://gitcode.com/colorEagleStdio/pyqtux.git

第一章:前言与项目背景
1.1 项目缘起
飞鸽传书(IPMsg)是一款经典的局域网即时通讯软件,诞生于 Windows 平台,以其高效的文件传输能力和无需服务器的特点,成为企业和校园局域网中不可或缺的工具。iptux 是飞鸽传书协议在 Linux 平台上的开源实现,继承了飞鸽传书的核心功能,同时扩展了群组、共享文件等特性。
然而,随着 Windows 平台上飞鸽传书的逐步停止更新,以及 Linux 发行版对 iptux 的支持参差不齐,用户面临着跨平台互操作的难题。本项目旨在利用现代 Python 技术栈,在 Windows 平台上复刻 iptux 的完整功能,实现与原版 iptux 和飞鸽传书的完全协议兼容。
1.2 技术选型与工具链
开发环境
- 主开发机:Windows 10
- 协议对照机:Linux 开发机,运行原版 iptux 0.8.3
技术栈
- 语言:Python 3.10+(Windows)/ Python 3.11(Linux)
- GUI框架:PyQt6(Windows)/ PyQt5(Linux)
- 网络通信:asyncio 异步网络编程
- 测试框架:pytest
AI 工具链
- IDE:Trae AI 辅助开发环境 Solo模式
- 模型:GLM5.2大语言模型(代码生成、调试、文档编写)
- 测试验证:Wireshark / tcpdump 抓包分析
Shell 工作流
项目采用脚本化策略:
- 复杂命令(SSH、rsync、管道等)通过写
.sh文件执行 - 这种方式避免了 Shell 兼容性问题,确保跨平台脚本一致性
1.3 目标与约束
核心目标
- 协议完全兼容:与 iptux 0.8.3、飞鸽传书字节级协议兼容
- 功能完整复刻:实现好友发现、消息收发、文件传输、头像签名等所有核心功能
- 跨平台运行:支持 Windows 和 Linux
- 独立控制台版本:核心层无 UI 依赖,可独立运行控制台版
硬约束
- 核心层零 PyQt 依赖 :
pyqtux/core/目录必须纯 Python,可在无 GUI 环境运行 - 协议字节级兼容性:分隔符、命令字、报文格式必须与原版完全一致
- 默认端口 2425:与原版 iptux/飞鸽传书保持一致
- 编码兼容:支持 GB18030、GBK、Big5 到 UTF-8 的自动转换
开发周期
项目计划在 24 小时内完成,分为 6 个阶段、24 个任务,每个阶段都有明确的可验证产出。
第二章:协议分析与架构设计
2.1 IPMsg/iptux 协议深度剖析
协议基础
IPMsg 协议是一种基于 UDP/TCP 的局域网即时通讯协议,采用明文传输,具有简单高效的特点。核心报文格式如下:
IPMsg 报文:version:packet_no:sender:host:command:additional\0extras\0...
- 前 5 个字段以冒号
:分隔 - iptux 扩展段以
\0分隔,前 3 段固定为group\0icon\0encoding - 文件名中的冒号需要转义为
::
关键命令字
| 命令 | 值 | 用途 |
|---|---|---|
BR_ENTRY |
0x101 | 上线广播(带 ABSENCEOPT) |
ANSENTRY |
0x103 | 应答上线(带 ABSENCEOPT) |
BR_EXIT |
0x2 | 下线通知 |
BR_ABSENCE |
0x4 | 信息变更 |
SENDMSG |
0x20 | 发送消息 |
RECVMSG |
0x21 | 消息回执 |
IPTUX_SENDICON |
0xFE | 发送头像(UDP) |
IPTUX_SEND_SIGN |
0xFC | 发送签名(UDP) |
IPTUX_SENDSUBLAYER |
0xFD | 底层数据(TCP,照片/图片) |
协议扩展
iptux 在 IPMsg 基础上扩展了以下功能:
- 扩展字段:BR_ENTRY/ANSENTRY 报文中携带 group、icon、encoding 信息
- 头像传输:UDP SENDICON + SHA256 去重
- 个性签名:UDP SEND_SIGN
- 形象照片:TCP SUBLAYER + PHOTOPICOPT
- 内嵌图片消息:TCP SUBLAYER + MSGPICOPT
文件传输流程
文件传输是协议中最复杂的部分,分为三个阶段:
- UDP 文件信息通知:发送方通过 SENDMSG + FILEATTACHOPT 发送文件列表
- TCP 连接建立:接收方主动连接发送方,请求文件数据
- 数据传输:发送方按 8KB 分块发送文件内容
目录传输还涉及虚拟文件系统(AnalogFS)的模拟:
- 发送目录头(大小为 0,DIR_ATTR 属性)
- 递归发送子目录和文件
- 发送 RETPARENT 标记返回父目录
2.2 架构设计原则
分层架构
项目采用清晰的三层架构:
┌─────────────────────────────────────────────┐
│ UI 层(PyQt6) │
│ MainWindow / DialogPeer / DialogGroup │
│ TransWindow / ShareFile / DataSettings │
├─────────────────────────────────────────────┤
│ 事件桥接层(CoreBridge) │
│ Qt 信号 ↔ 核心层事件的双向转换 │
├─────────────────────────────────────────────┤
│ 核心层(纯 Python) │
│ CoreThread / CommandBuilder / Packet │
│ UdpDataHandler / TcpDataHandler │
│ SendFile / RecvFile / AnalogFS │
└─────────────────────────────────────────────┘
设计原则
- 核心层零 UI 依赖 :
pyqtux/core/目录完全独立,可运行控制台版 - 事件驱动架构:核心层通过事件系统与 UI 解耦
- 协议字节级兼容:所有报文构造和解析严格遵循原版格式
- 测试驱动开发:每个功能模块都有完整的单元测试
- 跨平台兼容:配置路径、网络接口等采用平台自适应
模块职责
| 模块 | 职责 | 关键文件 |
|---|---|---|
| 协议常量 | 命令字、选项、文件属性定义 | ipmsg.py |
| 报文处理 | IpmsgPacket 解析与构造 | packet.py |
| 编码转换 | GB18030/GBK/Big5 → UTF-8 | encode.py |
| 数据模型 | PalInfo、FileInfo 等 | models.py |
| 命令构造 | 所有协议命令的构造方法 | command.py |
| UDP 处理 | UDP 报文分派与处理 | udp_data.py |
| TCP 处理 | TCP 连接分派(文件/照片) | tcp_data.py |
| 文件传输 | SendFile、RecvFile、AnalogFS | send_file.py, recv_file.py, analog_fs.py |
| 核心服务 | asyncio 事件循环、好友管理 | core_thread.py |
2.3 开发计划与里程碑
六阶段开发计划
| 阶段 | 主题 | 任务数 | 关键产出 | 测试数 |
|---|---|---|---|---|
| 1 | 项目骨架与协议常量 | 4 | 可导入的空项目骨架 | 224 |
| 2 | 核心层:报文与数据模型 | 5 | 报文解析/构造单测通过 | 402 |
| 3 | 核心层:网络服务与控制台版 | 5 | 控制台全功能版本 | 734 |
| 4 | UI 层:主窗口与好友列表 | 4 | 可见好友列表的 GUI | 870 |
| 5 | UI 层:聊天与文件传输 | 4 | 完整聊天+文件传输 GUI | 1033 |
| 6 | UI 层:辅助功能与打磨 | 2 | 发布就绪的完整应用 | 1118 |
里程碑
- 阶段 3 结束:拥有可用的控制台版本,可与原版 iptux 互操作
- 阶段 5 结束:完整 GUI 功能,所有核心测试通过
- 阶段 6 结束:发布就绪,三端互操作矩阵全部验证通过
协同策略
项目采用主开发机 + 协议对照机的双机验证模式:
- 跨平台单测:推送代码到对照机,执行 pytest 验证核心层兼容性
- 协议对照:对照机上运行原版 iptux 0.8.3,本机 pyqtux 与之互操作
- 双实例测试:对照机上部署 pyqtux 控制台版,进行真实双机通信
所有依赖外部环境的测试用标记,离线时自动跳过。
第三章:核心层开发(阶段1-3)
3.1 阶段1:项目骨架与协议常量
阶段 1 的目标是搭建项目结构,定义所有协议常量,为后续开发奠定基础。
任务 1.1:创建项目骨架
创建了完整的项目结构:
pyqtux/
├── main.py # 程序入口
├── pyproject.toml # 项目元数据与依赖
├── requirements.txt # 依赖清单
├── pyqtux/
│ ├── __init__.py
│ ├── core/ # 核心层
│ ├── ui/ # UI 层
│ └── utils/ # 工具
└── tests/
├── conftest.py
└── integration/ # 集成测试
任务 1.2:协议常量定义
在 ipmsg.py 中定义了所有协议常量:
CommandMode枚举:所有命令模式(BR_ENTRY、SENDMSG、RECVMSG 等)CommandOptIntFlag:所有命令选项(SENDCHECKOPT、FILEATTACHOPT 等)FileAttr枚举:文件类型属性(REG_ATTR、DIR_ATTR、RETPARENT_ATTR)- 辅助函数:
get_mode()、get_opt() - 常量:
IPTUX_VERSION=1、IPMSG_PORT=2425、MAX_UDPLEN=8192
任务 1.3:数据模型定义
在 models.py 中定义了核心数据结构:
PalKey:好友唯一标识(ipv4 + port)PalInfo:好友信息(昵称、群组、头像、签名、编码等)FileInfo:文件信息(文件ID、路径、大小、时间、属性)NetSegment:网段管理(count()、nth_ip()、contain_ip())
任务 1.4:事件类型与配置管理
- events.py:定义了 14 种事件类型(PalOnlineEvent、NewMessageEvent、SendFileFinishedEvent 等)
- config.py:
IptuxConfig:JSON 配置读写,与原版兼容ProgramData:运行时数据管理- 跨平台路径处理(Windows %APPDATA% / Linux ~/.config)
阶段 1 成果:224 个单元测试全部通过,跨平台验证成功。
3.2 阶段2:报文与数据模型
阶段 2 的核心目标是实现报文构造/解析、编码转换和文件信息编解码。
任务 2.1:报文构造与解析
packet.py 实现了 IpmsgPacket dataclass:
to_bytes(encode):序列化报文字节流from_bytes(data, default_encode):反序列化解析报文- 处理
\0分隔的 iptux 扩展字段 - 处理冒号分隔的字段解析
关键发现:协议文档附录 B.1 存在错误,BR_ENTRY 实际值为 0x101 (257),而非文档所写的 0x105 (261)。这一发现通过抓取真实 iptux 0.8.3 报文得到验证。
任务 2.2:编码转换工具
encode.py 实现了中文编码转换:
convert_encode(data, to_encode, from_encode):字节流编码转换validate_utf8(data, codeset):验证并转换为 UTF-8make_valid_utf8(data):强制转为有效 UTF-8
支持 GB18030、GBK、Big5 等常见中文编码,处理了 Big5 字节在 GB18030 中也能解码但结果错误的边界情况。
任务 2.3:文件信息编解码
在 packet.py 中集成了文件信息编解码:
encode_file_info(file_info):编码为 IPMsg 格式decode_file_infos(data):解码文件信息列表
文件信息格式:fileid:filename:filesize:filectime:fileattr:\a
关键发现 :文件名中的冒号 : 需要转义为 ::,否则会导致协议解析错误。
任务 2.4:网络工具函数
network.py 实现了跨平台网络工具:
get_broadcast_addresses():跨平台获取广播地址(Windows 使用 psutil,Linux 使用 ioctl)- IP 地址转换和广播地址计算
任务 2.5:格式化工具
format.py 实现了数据格式化:
numeric_to_size(n):字节大小格式化(B/KiB/MiB/GiB/TiB)numeric_to_rate(n):速率格式化(B/s/K/s/M/s/G/s)numeric_to_time(n):时间长度格式化(HH:MM:SS)
阶段 2 成果:402 个单元测试通过,真实报文解析验证成功,协议文档勘误确认。
3.3 阶段3:网络服务与控制台版本
阶段 3 是项目的关键里程碑,交付可用的控制台版本。
任务 3.1:命令构造器
command.py 实现了 CommandBuilder 类,包含所有协议命令的构造方法:
broadcast(port):广播上线send_message(pal, msg):发送消息(带重试机制)send_reply(pal, packet_no):消息回执send_file_info(pal, opt, extra):发送文件信息send_my_icon(pal, icon_data):发送头像send_my_sign(pal):发送签名send_sublayer(pal, opt, path):发送底层数据(照片/图片)
包号自增管理通过 property 实现,确保每个命令有唯一的 packet_no。
任务 3.2:UDP 数据处理
udp_data.py 实现了 UdpDataHandler 类,对应原版 UdpDataService:
- 命令分派:根据
get_mode(command)调用对应处理函数 _on_entry:好友上线处理(创建/更新 PalInfo,回应 ANSENTRY)_on_sendmsg:消息接收(回执、去重、文件附件提取)_on_recvmsg:回执处理_on_send_icon:头像接收_on_send_sign:签名接收
任务 3.3:TCP 数据处理与文件传输
这是阶段 3 最复杂的部分,涉及多个模块:
- tcp_data.py:TCP 连接分派(GETFILEDATA / GETDIRFILES / SUBLAYER)
- send_file.py:文件信息发送、文件数据发送(常规文件 + 目录递归)
- recv_file.py:文件信息接收、文件数据接收
- analog_fs.py:虚拟文件系统(chdir/mkdir/open,支持目录递归传输)
- trans_task.py:传输任务管理
任务 3.4:核心服务(CoreThread)
core_thread.py 是核心服务的中枢,基于 asyncio 实现:
start():绑定 UDP/TCP 2425 端口、启动接收、广播上线stop():通知下线、关闭 socket- UDP 接收循环(asyncio DatagramProtocol)
- TCP 接收循环(asyncio Server + Protocol)
- 好友列表管理(
get_pal、attach_pal、del_pal、update_pal) - 传输任务管理(
register_trans_task、terminate_trans_task) - 事件分发(
emit_event、on_event)
设计要点:
- 事件循环在独立线程运行,UI/控制台主线程不被阻塞
udp_send通过call_soon_threadsafe保证线程安全- 好友列表用
dict[PalKey, PalInfo]索引,O(1) 查找
任务 3.5:控制台版本
console.py 实现了无 GUI 的控制台交互界面:
list:列出在线好友send <ip> <msg>:发送消息file <ip> <path>:发送文件share/share add <path>:管理共享文件detect <ip>:探测好友exit:退出
实时显示收到的事件(上线/下线/消息/文件请求)。
阶段 3 成果:
- 控制台全功能版本交付:可与原版 iptux 互操作
- 互操作三连测通过 :
- 发现 ✅:互相出现在好友列表
- 消息 ✅:中文消息正确送达
- 文件 ✅:文件完整传输
- 734 个单元测试 + 7 个集成测试通过
后续修复 :阶段 3 完成后发现 send_message 的 RECVMSG 回执识别 bug,根因为 packet_no 自增 property 被调用两次,导致 pal.rpacketn 与实际 packet_no 不一致。修复后双向消息回执均能正确识别。
第四章:UI层开发(阶段4-5)
4.1 阶段4:主窗口与好友列表
阶段 4 的目标是实现 GUI 主框架,显示好友列表,响应上线/下线事件。
任务 4.1:UI 框架与事件桥接
application.py 实现了 UI 层的核心框架:
Application类:管理 QApplication、CoreThreadWrapper、各窗口CoreBridge(QObject):定义所有 UI 信号(pal_online、pal_update、new_message 等),共 14 个信号CoreThreadWrapper(QThread):在独立线程运行 asyncio loop,转发核心层事件到 Qt 信号
main.py 是程序入口,创建 Application 并运行。
设计要点:
- 核心层事件通过
CoreBridge转换为 Qt 信号,实现 UI 与核心层的解耦 - asyncio 事件循环在独立线程运行,不阻塞 Qt 主线程
任务 4.2:主窗口与好友树
main_window.py 实现了主窗口:
- 工具栏:探测好友、共享文件、传输管理、日志、关于、设置
- 好友树:按群组/网段分组显示好友(头像 + 昵称 + IP + 群组)
- 信息面板:显示选中好友的详细信息
- 状态栏:显示在线好友数、当前状态
models.py 实现了好友树模型:
PalTreeModel(QAbstractItemModel):好友树数据模型GroupNode、PalNode:树节点类型- 支持按昵称/IP 排序
- 右键菜单:发送消息、请求共享、修改信息、删除好友
任务 4.3:资源与图标
resources.py 实现了图标缓存与访问:
- 使用
importlib.resources加载包内图标资源 - 32 个内置头像图标(icon-blowfish、icon-dog、icon-penguin 等)
- 界面图标(iptux-icon、tip-send、tip-recv 等)
资源文件位于 pyqtux/resources/icons/ 目录,分为 app、avatar、menu、tip 四类。
任务 4.4:系统托盘与基础对话框
- status_icon.py:系统托盘图标(显示/隐藏主窗口、退出)
- detect_pal.py:探测好友对话框(输入 IP,发送探测包)
- about_dialog.py:关于对话框
- data_settings.py:系统设置对话框(个人信息、网络、系统三选项卡)
阶段 4 成果:8 个源文件 + 4 个测试文件 + 资源目录,136 个 UI 单测全部通过。
4.2 阶段5:聊天与文件传输
阶段 5 的目标是实现完整聊天与文件传输 GUI。
任务 5.1:聊天窗口基类与单人聊天
dialog_base.py 实现了聊天窗口基类 DialogBase:
- 历史记录区:使用 QTextBrowser(支持 HTML 和内嵌图片)
- 输入区:QTextEdit(支持拖拽文件、粘贴图片)
- 文件附件区:QTreeView(待发送文件列表)
- 工具栏:发送/附件/文件夹/图片按钮
- 拖拽支持:拖入文件自动添加附件
dialog_peer.py 实现了单人聊天窗口:
- 标题显示好友信息
- 接收文件区:待接收/已接收文件列表,接受/拒绝按钮
- 发送消息:调用
core.send_message - 发送文件:构造文件信息,发送 SENDMSG + FILEATTACHOPT
- 接收图片消息:TCP SUBLAYER + MSGPICOPT
关键修复:
- 初始使用 QPlainTextEdit 只支持纯文本,无法显示图片
- 改用 QTextBrowser 支持 HTML 和内嵌图片
- 使用
QTextDocument.addResource()添加图片资源,第二参数必须是 QUrl 类型
任务 5.2:群组聊天窗口
dialog_group.py 实现了群组聊天窗口:
- 成员列表区:
MemberTreeWidget(昵称/IP/群组三列) - 群发消息:遍历群组成员调用
send_group_msg - 广播消息:IPTUX_SENDMSG + BROADCASTOPT
- 网段消息:IPTUX_SENDMSG + SEGMENTOPT
- 分组消息:IPTUX_SENDMSG + GROUPOPT
任务 5.3:文件传输窗口
trans_window.py 实现了文件传输管理窗口:
TransWindow(QMainWindow,单例)TransTaskModel(QAbstractTableModel):传输任务表格模型- 列:状态、任务、对方、IP、文件名、进度、完成/总大小、耗时、剩余、速率
- 工具栏:清除已完成、终止任务、刷新
- QTimer 500ms 自动刷新 +
bridge.trans_tasks_changed信号触发重载
share_file.py 实现了共享文件管理对话框:
- 添加/删除共享文件(fileid 从 1 起 < MAX_SHAREDFILE=10000)
- 持久化到
ProgramData._shared_file_infos
任务 5.4:好友信息修改与日志
- revise_pal.py:修改好友信息对话框(昵称、群组、编码、头像、兼容性)
- log_window.py:日志查看窗口(系统日志 + 按好友聊天日志)
- logger.py:日志系统
阶段 5 成果 :7 个源文件 + 6 个测试文件,180 个 UI 单测全部通过,全量回归 1033 passed。
4.3 阶段6:辅助功能与打磨
阶段 6 的目标是完善细节,达到发布就绪状态。
任务 6.1:头像/签名/形象照片完整支持
实现了头像接收与显示(UDP SENDICON + SHA256 缓存去重)、个性签名显示(UDP SEND_SIGN)、形象照片接收与显示(TCP SUBLAYER PHOTOPICOPT)。
关键修复 :_on_entry/_on_ansentry 未调用 send_feature_data,导致好友上线时不主动发送头像/签名。
任务 6.2:最终集成测试与打包
完成了完整功能集成测试和与原版 iptux 的互操作测试。
额外优化:
-
消息换行修复 :QTextBrowser 的
insertHtml对连续块级元素不会自动创建段落分隔符,导致消息全挤一行。改用cursor.insertBlock()+cursor.insertText()显式段落分隔。 -
宽屏布局重构:会话窗口从垂直布局改为水平+垂直混合布局:
- 水平 QSplitter 作为顶层(左大区 + 右侧边栏)
- 左大区保留垂直 QSplitter(聊天历史 + 输入区)
- 右侧侧边栏放附件树 + 操作按钮
- 默认尺寸 960×540(16:9)
阶段 6 成果 :全量回归 1118 passed,三端互操作矩阵全部验证通过。
第五章:协议兼容性与互操作测试
5.1 三端互操作矩阵
项目采用三端验证策略:本机 pyqtux (Windows)、Linux pyqtux、Linux 原版 iptux 0.8.3。最终验收结果如下:
| 发送方 \ 接收方 | 本机 pyqtux (Win) | Linux pyqtux | Linux 原版 iptux 0.8.3 |
|---|---|---|---|
| 本机 pyqtux | --- | ✅ 发现+消息+文件 | ✅ 发现+消息+文件 |
| Linux pyqtux | ✅ 发现+消息+文件 | --- | 待测(需 GUI 手动) |
| Linux 原版 iptux | ✅ 头像+签名(自动 FeatureData) | 待测 | --- |
验证记录
2026-07-17:阶段 3 验收门通过
- 双向互操作三连测全部成功:
- 发现 ✅:互相出现在好友列表
- 消息 ✅:中文消息正确送达
- 文件 ✅:文件完整传输
2026-07-18:双向互操作验证通过
- 双向消息+文件已通过
- 反向测试:发现 ✅、消息 ✅(RECVMSG 回执双向识别)、文件 ✅(UTF-8 中文内容完整)
2026-07-18:头像/签名互通验证通过
- 头像 + 签名字节级互通
- SHA256 缓存 + sign 正确处理
5.2 真实报文对照验证
抓包验证流程
- 在对照机上启动原版 iptux 0.8.3
- 使用
tcpdump -i any port 2425 -w /tmp/iptux.pcap抓取报文 - 将 pcap 文件拉回本机
- 使用解析工具解析并与
IpmsgPacket.from_bytes结果对比
BR_ENTRY 报文对照
真实抓包(iptux 0.8.3):
version="1_iptux 0.8.3"
packet_no=1784295655
sender="testuser"
host="devbox"
command=0x101 (BR_ENTRY + ABSENCEOPT)
additional="TestUser"
extras=["group", "icon-qq.png", "utf-8"]
pyqtux 解析结果:完全一致,字段值无偏差。
RECVMSG 回执对照
对比 iptux 0.8.3 和 pyqtux 的 RECVMSG 回执报文:
| 字段 | iptux 0.8.3 | pyqtux |
|---|---|---|
| command | 0x121 | 0x121 |
| mode | 0x21 | 0x21 |
| opt | 0x100 | 0x100 |
| additional | "1784295655" | "1784295655" |
| 分隔符 | : |
: |
| 终止符 | \0 |
\0 |
结论:RECVMSG 回执报文字节级完全一致,协议兼容性得到验证。
文件传输协议对照
通过 Wireshark 分析抓包中的 TCP 目录数据流,发现并修复了以下协议差异:
- UDP 文件信息末尾冒号 :iptux 0.8.3 格式为
fileid:filename:filesize:filectime:fileattr:\x07,早期实现多一个冒号导致解析异常 - TCP 文件头 filesize 补零 :iptux 0.8.3 使用 9 位零填充十六进制
%09x,早期使用可变长度%x - 子目录头重复发送:早期在发送目录时重复发送子目录头,导致 iptux 段错误
5.3 协议文档勘误
附录 B.1:BR_ENTRY 命令值
文档值 :0x105 (261)
实际值:0x101 (257)
通过抓取真实 iptux 0.8.3 BR_ENTRY 报文证实,BR_ENTRY = 0x1(上线命令)+ 0x100(ABSENCEOPT)= 0x101。
附录 B.3:SENDMSG + FILEATTACHOPT
文档值 :0x202020 (2103296)
实际值:0x200020 (2097184)
正确计算:SENDMSG = 0x20 + FILEATTACHOPT = 0x200000 = 0x200020。
重要发现
- iptux 扩展字段顺序 :
[group, icon, encoding],is_iptux_compatible需要 >=3 个 extras - 版本字符串区分 :
- iptux:
1_iptux 0.8.3 - 飞鸽传书:
1_lbt6_0#...
- iptux:
- 编码自动检测 :
from_bytes先尝试 UTF-8,失败则回退到 default_encode 参数 - 文件时间戳处理:Windows 时间戳可能为负数,需转换为无符号 32 位整数
飞鸽传书兼容性
飞鸽传书(Feige)报文格式与 iptux 略有差异,主要体现在:
- 版本字符串格式不同(
1_lbt6_0#...vs1_iptux ...) - 扩展字段可能缺失或格式不同
pyqtux 通过 compat=False 标记区分飞鸽传书报文,确保协议兼容。
5.4 互操作测试脚本
项目提供了完整的互操作测试脚本和集成测试框架,所有依赖外部环境的测试用标记,离线时自动跳过。
第六章:技术难点与解决方案
6.1 编码兼容问题
中文编码歧义
问题描述:Big5 编码的"你好"字节也是合法的 GB18030 编码,但解码结果完全不同。这导致自动检测编码时可能产生错误的解码结果。
解决方案:
- 在
make_valid_utf8中优先尝试 UTF-8 - 如果 UTF-8 解码失败,按优先级尝试 GB18030 → GBK → Big5
- 每个编码尝试后验证结果是否合理(通过字符范围检查)
- 所有编码都失败时使用
errors="replace"降级处理
跨平台编码转换
问题描述:不同平台默认编码不同,Windows 使用 GBK,Linux 使用 UTF-8。
解决方案:
- 核心层统一使用 UTF-8 内部表示
- 协议层面支持多种编码(GB18030、GBK、Big5)
from_bytes自动检测编码并转换为 UTF-8to_bytes根据对方的编码设置转换为对应编码
6.2 文件传输协议细节
UDP 文件信息格式
问题描述 :iptux 0.8.3 的 UDP 文件信息格式为 fileid:filename:filesize:filectime:fileattr:\x07,早期实现多了一个末尾冒号,导致 iptux 解析异常。
解决方案:
- 修改
encode_file_info函数,移除末尾多余的冒号 - 添加回归测试确保格式正确
TCP 文件头 filesize 补零
问题描述 :iptux 0.8.3 使用 9 位零填充十六进制 %09x(如 0000007db),早期使用可变长度 %x(如 7db)。
解决方案:
- 修改
_send_dir_recursive中的文件头构造逻辑 - 使用
f"{filesize:09x}"确保 9 位零填充 - 更新受影响的测试断言
子目录头重复发送
问题描述 :早期在发送目录时,父循环会预先发送目录头,而 _send_dir_recursive 内部也会发送,导致重复发送子目录头,iptux 接收到重复目录头后段错误。
解决方案:
- 修改
send_file.py,移除父循环中预先发送目录头的逻辑 - 确保目录头仅由递归函数发送
- 添加回归测试
test_send_nested_dir_no_duplicate_subdir_header
目录大小计算错误
问题描述 :使用 os.path.getsize() 计算目录大小会返回目录元数据大小(通常 4096 字节),而非目录内容的真实大小。
解决方案:
- 使用
AnalogFS().ftwsize(filepath)递归计算目录总大小 - 在多个模块(send_file、dialog_base、share_file、console)中统一使用此方法
- 添加测试验证目录大小计算正确性
文件时间戳处理
问题描述:Windows 上文件时间戳可能为负数(如 1970 年前的文件),直接发送会导致协议异常。
解决方案:
- 转换为无符号 32 位整数:
mtime & 0xFFFFFFFF - 确保时间戳在协议允许的范围内
传输失败时的目录层级混乱
问题描述 :文件发送失败时直接 return,导致 afs.chdir("..") 未执行,造成目录层级混乱。
解决方案:
- 在
send_file.py中添加afs.chdir("..")和self._terminated = True后再返回 - 使用 try/finally 确保目录回退逻辑一定执行
6.3 Qt 与 asyncio 集成
事件循环线程安全
问题描述:Qt 主线程和 asyncio 事件循环在不同线程运行,直接调用会导致线程安全问题。
解决方案:
- 使用
CoreThreadWrapper将 asyncio 事件循环封装在 QThread 中 - 通过 Qt 信号槽机制跨线程通信
udp_send使用call_soon_threadsafe保证线程安全
QTextBrowser 消息换行
问题描述 :insertHtml("<div>/<p>...") 对连续块级元素不会自动创建段落分隔符,导致消息全挤一行。
解决方案:
- 改用
cursor.insertBlock()+cursor.insertText()显式段落分隔 insertText处理纯文本可天然防 HTML 注入,无需html.escape
QTextDocument.addResource 参数类型
问题描述 :PyQt6 中 QTextDocument.addResource() 的第二参数必须是 QUrl 类型,传入字符串会导致图片无法显示。
解决方案:
- 将图片路径转换为 QUrl:
QUrl.fromLocalFile(path) - 添加类型检查确保参数正确
好友列表时序问题
问题描述:MainWindow 创建前核心层可能已发出好友上线事件,但此时没有信号接收方,导致好友列表看不到已在线的好友。
解决方案:
- 在
main_window.py中新增_sync_existing_pals方法 - MainWindow 创建后主动从核心层同步现有好友
- 调整
application.py中的启动顺序
QFontComboBox.setCurrentFont 类型错误
问题描述 :ProgramData.font 存储的是字体 family 名字符串,但 QFontComboBox.setCurrentFont 需要 QFont 对象。
解决方案:
- 在
data_settings.py中添加 QFont 导入 - 修改调用为
setCurrentFont(QFont(font_string))
6.4 跨平台部署
Shell 环境差异
问题描述:不同 Shell 环境语法差异,不支持某些 bash 特性。
解决方案:
- 采用脚本化策略:复杂命令写
.sh文件再执行 - 使用无 BOM 的
.sh文件 - 避免内联执行形式,一律写文件再执行
抓包链路层差异
问题描述 :Linux 上 tcpdump -i any 使用 Linux SLL2(linktype 276,header 20 字节),而非 Ethernet(14 字节)。
解决方案:
- 在解析工具中处理不同链路层类型
- 确保 Wireshark 能正确解析抓包文件
6.5 协议层疑难问题
RECVMSG 回执识别失败
问题描述 :send_message 报 TimeoutError,但实际已回复 RECVMSG 回执。
根因分析 :packet_no 自增 property 被调用两次(一次在 send_message,一次在 _make_packet),导致 pal.rpacketn(N) ≠ 实际 packet_no(N+1)。
解决方案:
- 修改
send_message逻辑,先调用_make_packet,再提取pkt.packet_no,最后设置pal.rpacketn - 添加回归测试确保回执识别正确
iptux 0.8.3 不发送 RECVMSG
问题描述 :iptux 0.8.3 不针对 SENDMSG+SENDCHECKOPT 主动发 RECVMSG 回执。
解决方案:
- pyqtux 兼容此行为:消息送达即视为成功
- 记录此行为为已知限制,不视为 bug
形象照片协议支持
问题描述:形象照片需要通过 TCP SUBLAYER + PHOTOPICOPT 发送,协议较为复杂。
解决方案:
- 在
tcp_data.py中增强 SUBLAYER 处理逻辑 - 在
core_thread.py中添加send_msg_pic()方法 - 支持内嵌图片消息(MSGPICOPT)和形象照片(PHOTOPICOPT)
6.6 UI 布局优化
宽屏布局重构
问题描述:原布局为垂直布局,在 16:9 宽屏显示器上显示效果不佳。
解决方案:
- 使用水平 QSplitter 作为顶层布局容器
- 左大区保留垂直 QSplitter(聊天历史 + 输入区)
- 右侧侧边栏放附件树 + 操作按钮(清空/删除/发送)
- 工具栏按钮(附件/文件夹/图片)留在输入区上方
- 默认尺寸改为 960×540(16:9)
子类兼容性
问题描述 :DialogPeer 和 DialogGroup 通过 self._splitter.insertWidget(0, ...) 插入额外区域,布局重构可能破坏此功能。
解决方案:
- 保留
self._splitter作为左大区的垂直布局 - 子类的插入逻辑仍然生效,无需修改
- 添加回归测试验证子类兼容性
第七章:经验总结与未来展望
7.1 AI 驱动开发的体会
AI 辅助的优势
- 快速原型开发:大语言模型能够根据需求描述快速生成完整的代码框架和实现,大大缩短了开发周期
- 协议解析加速:AI 能够快速理解复杂的协议文档,并生成对应的解析代码
- 调试效率提升:遇到问题时,AI 能够分析错误信息,提供可能的解决方案
- 文档自动化:AI 能够自动生成测试用例、注释和文档,确保代码质量
- 跨平台支持:AI 能够处理不同平台的差异,提供跨平台兼容的解决方案
AI 辅助的挑战
- 协议细节偏差:AI 生成的代码可能与原版协议存在细微差异,需要通过真实报文对照验证
- 环境差异:AI 不了解本地开发环境的特殊性,需要手动调整
- 复杂逻辑处理:对于复杂的递归逻辑(如目录传输),AI 可能需要多次迭代才能正确实现
- 测试覆盖不足:AI 生成的测试用例可能不够全面,需要人工补充边缘场景测试
最佳实践
- 测试驱动开发:先编写测试用例,再实现功能,确保每个功能都有验证
- 真实报文对照:使用 tcpdump/Wireshark 抓取真实报文,验证协议实现的正确性
- 渐进式开发:分阶段开发,每个阶段完成后进行验证,避免一次性实现所有功能
- 代码审查:定期审查 AI 生成的代码,确保符合项目规范和最佳实践
- 知识积累:将发现的问题和解决方案记录到项目记忆中,供后续开发参考
7.2 工程实践经验
协议兼容性
- 文档不可完全信赖:协议文档可能存在错误,需要通过真实抓包验证
- 字节级兼容:协议实现必须精确到字节级别,任何细微差异都可能导致互操作失败
- 扩展字段处理:正确处理协议扩展字段,确保与原版 iptux 和飞鸽传书兼容
- 编码兼容性:支持多种中文编码(GB18030、GBK、Big5),确保跨平台中文显示正确
跨平台开发
- 配置路径自适应:根据操作系统自动选择配置和缓存路径(Windows %APPDATA% / Linux ~/.config)
- 网络接口适配:Windows 使用 psutil 获取广播地址,Linux 使用 ioctl
- Shell 环境差异:不同 Shell 的语法差异,需要采用脚本化策略
- PyQt 版本差异:Windows 使用 PyQt6,Linux 使用 PyQt5,需要处理 API 差异
测试策略
- 单元测试优先:每个功能模块都有完整的单元测试,确保基础功能正确
- 集成测试补充:使用对照机进行真实互操作测试,验证跨平台兼容性
- 标记跳过机制 :依赖外部环境的测试用
@pytest.mark标记,离线时自动跳过 - 回归测试保障:全量回归测试确保修改不会破坏已有功能
架构设计
- 分层架构:核心层、事件桥接层、UI 层清晰分离,降低耦合度
- 事件驱动:使用事件系统解耦核心层和 UI 层,便于测试和扩展
- 控制台优先:先实现无 UI 依赖的控制台版本,再构建 GUI
- 协议文档化:详细记录协议规范和设计决策,便于后续维护
7.3 未来改进方向
功能增强
- 语音消息:支持语音消息的录制和播放
- 视频消息:支持视频消息的发送和接收
- 文件预览:在发送前预览文件内容
- 断点续传:支持文件传输中断后的断点续传
- 群文件共享:支持群组内文件共享
- 消息加密:支持端到端消息加密
- 多语言支持:支持英文、日文等多种语言界面
性能优化
- 大文件传输优化:支持更大文件的高效传输
- 批量消息处理:优化大量消息的处理性能
- 内存管理:优化内存使用,避免大文件传输时的内存占用过高
- 并发连接:支持更多并发连接
平台扩展
- macOS 支持:添加 macOS 平台支持
- 移动端支持:开发 Android/iOS 移动端版本
- Web 版本:开发基于 Web 的版本,支持浏览器访问
开发工具
- 协议调试器:开发专用的协议调试工具,便于分析和调试协议问题
- 性能分析工具:添加性能分析功能,帮助定位性能瓶颈
- 自动化测试框架:完善自动化测试框架,支持更多场景的自动测试
社区贡献
- 文档完善:完善项目文档,包括用户手册、开发者指南等
- 示例代码:提供更多示例代码,帮助开发者理解和扩展项目
- Bug 报告:建立完善的 bug 报告和处理流程
- 功能请求:建立功能请求和优先级排序机制
7.4 项目成果总结
交付成果
- 完整的 Python 版 iptux:与原版 iptux 0.8.3 字节级协议兼容
- 跨平台支持:Windows 和 Linux 均可运行
- 控制台版本:无 UI 依赖,可在服务器环境运行
- GUI 版本:完整的 PyQt6 界面,支持所有核心功能
- 测试套件:1118 个单元测试,覆盖所有核心功能
- 文档:完整的协议文档、技术方案、开发计划和用户手册
互操作验证
- ✅ pyqtux ↔ pyqtux:双向发现、消息、文件传输
- ✅ pyqtux ↔ iptux 0.8.3:双向发现、消息、文件传输、头像、签名
- ✅ pyqtux ↔ 飞鸽传书:协议兼容(标记为 compat=False)
技术亮点
- asyncio 异步网络:高效的异步网络通信,支持大量并发连接
- 事件驱动架构:解耦核心层和 UI 层,便于测试和扩展
- 协议字节级兼容:与原版 iptux 完全协议兼容
- 测试驱动开发:完整的测试套件,确保代码质量
- 跨平台自适应:自动适配不同操作系统的差异
开发周期
项目在约 24 小时内完成了从需求分析到发布的全过程,包括:
- 协议分析和文档编写
- 6 个阶段、24 个任务的开发
- 完整的测试验证
- 三端互操作矩阵验证
这充分展示了 AI 辅助开发的高效性和可行性,为后续项目提供了宝贵的经验参考。
项目仓库
本项目已开源,仓库地址:https://gitcode.com/colorEagleStdio/pyqtux.git