基于P2P的局域网即时通信系统课设实现指南
2026/9/24 18:33:06 网站建设 项目流程

简介:一份基于P2P的局域网即时通信系统课程设计资源,面向广工计算机网络课程学生,解决局域网内图形界面消息与文件传输的课设需求。项目完整实现了用户注册、对等方在线扫描与列表获取、TCP连接收发消息和文件,服务端口固定为3333,并涵盖P2P通信、多线程、Socket编程等计网核心知识点。资源包内共158个文件,压缩包约20.77MB,以Java源文件、class编译文件、XML配置及Eclipse项目文件为主,同时包含JS、properties等辅助文件与文档说明,可直接导入开发环境运行和学习。已有424人学习下载,其中聊天窗口、文件发送适配、IP扫描等核心类实现清晰,便于理解界面与网络层的协同方式,可用于完成课设报告、代码讲解与答辩准备。对于需要快速上手计网课设的同学,可重点参考其对等方发现机制、消息收发线程模型和文件传输流程。

1. 这个课设题到底在考什么:P2P 不是标题党,是让你扔掉 C/S 思维

周三晚上,你打开课程设计题目列表,看到“基于P2P的局域网即时通信系统”,第一反应是翻课本找聊天室代码——结果发现教材里全是 C/S 模型:服务器转发、客户端连接。这个题目的坑就在这:课本教的聊天室架构,在这里恰好是扣分项。P2P 的意思是 Peer-to-Peer,局域网内每个节点既当客户端又当服务器,消息在两个终端之间直连,不经过任何中转。这个课设真正考的不是“会不会写 socket”,而是“能不能理解网络架构的本质区别”:C/S 依赖中心节点,P2P 没有中心节点,在线发现、消息路由、断线检测全都要自己设计。适合谁来读?正在做计网课设、但又不想把代码写成“伪 P2P”的学生,以及想快速搭一个局域网通信原型的开发者。下文按我实际做过的方案给一条能跑通的路线。

2. P2P 选型:先回答“服务端是谁”,再动手写代码

很多同学拿到这个题,第一反应是“我写个服务器,再写个客户端,客户端连服务器不就行了”——这就是典型的 C/S 思维。P2P 系统里,没有一台机器天然是“服务器”,每一台机器都同时具备服务能力和请求能力。但“完全没有中心”也会带来一个现实问题:一个新节点上线,怎么知道局域网里有哪些人?这就要先做架构选型。

2.1 两种 P2P 落地姿势:洪泛发现与索引服务器

P2P 系统里“找对等方”的经典做法有两种,课设最常见的就是这两种变体:

第一种是洪泛发现。新节点上线时,向局域网广播一条“我在线,我是谁”,所有收到这条广播的节点都单播回复自己的信息。这种方式没有中心,任何一台机器挂掉都不影响其他人,但代价是广播报文会泛洪到整个子网,节点多了会消耗带宽。早期 Gnutella 走的就是这条路。第二种是索引服务器模式:一台固定主机只维护“谁在线”的列表,不转发聊天内容,真正聊天时两个节点直接建立连接。这其实就是混合式 P2P(Napster 那种),它的在线发现依赖中心,但消息通道是 P2P 的。

对局域网课设来说,我一般建议选第一种,理由很直接:广播在单个子网内的实现成本最低,不需要额外部署服务器;而混合式 P2P 里“这台索引服务器挂了怎么办”往往会被答辩老师追问,你得额外解释。这里给一个简单的选型对比:

维度洪泛发现(纯 P2P)索引服务器(混合 P2P)
中心节点有(只做发现,不转发消息)
新节点上线成本广播一次向索引服务器注册
服务器故障影响新节点无法上线,已在线节点不受影响
实现难度低,但要部署一个常驻进程
答辩追问点广播风暴怎么避免索引服务器挂了怎么办

我实际做的时候选的是“UDP 广播发现 + TCP 点对点消息”,下面这节讲为什么这么组合。

2.2 为什么我选 UDP 广播 + TCP 点对点:方案能到 50 台以内的理由

UDP 负责“找人”,TCP 负责“聊天”,两个层次分开,这是局域网即时通信里最省事的组合,理由有三点。

第一,发现逻辑用 UDP 广播最自然。UDP socket 设置 SO_BROADCAST 之后,一条 sendto 就能把报文送到子网内所有主机,不需要知道对方 IP,也不用维护连接状态。TCP 广播是不存在的——TCP 是点对点连接,你连不上就是连不上,无法“广播”。第二,消息传输用 TCP 是为了可靠性。聊天内容不能被丢包,TCP 的确认重传机制保证对方收到,而且你不需要自己实现序号、重传、流控——计网课设的核心是“用对协议”,不是“重新发明协议”。第三,UDP 只负责在线状态,报文极小且丢失可容忍,TCP 只负责可靠数据传输,两者的职责边界非常清晰。这个方案能支撑多大规模?在在线状态用单播心跳维持的前提下(详见第 3 章),50 台机器以内没有任何压力。超过 50 台后广播和心跳流量会开始明显占用带宽,需要改成组播或索引服务器,但对课程设计来说,50 台已经非常充裕。

2.3 最容易被误解的“P2P 课设”:别把中转服务器写成消息中心

必须强调一个答辩必问的点:P2P 消息是端到端直连的。很多人的代码里有一台“服务器”,所有聊天消息都先发给它、由它转发给目标——这种架构无论你怎么解释,都是 C/S,不是 P2P。真正的 P2P 里,如果 A 要给 B 发消息,A 直接 connect B 的 IP 和端口,建立 TCP 连接后发送,消息全程不经过任何第三台机器。

有一个例外可以接受:你用一台固定主机做“用户发现”,它只维护在线列表,不转发任何聊天内容,聊天还是节点直连。这种是混合式 P2P,在答辩时强调“这台机器只做发现、不做中转”即可。如果你想让架构更纯粹,就干脆连发现也不要中心——全广播。我在这一版方案里用的是全广播,代码逻辑更简单,答辩时也不容易被追问出漏洞。

3. 实现用户发现与在线状态:UDP 广播的最小可跑通代码

确定选型后,第一步是实现“怎么发现对方”。下面这套代码我把“上线广播”“单播回复”“心跳维持”三个逻辑拆开写,前后连起来就是一个可运行的在线发现模块。

3.1 用 Python 跑通 UDP 广播的四步代码

直接看最小可跑通版本,发送广播端:

import socket import json MY_NAME = "host-001" UDP_PORT = 54200 # 固定的发现端口,所有节点一致 BROADCAST_ADDR = "255.255.255.255" # 全局广播地址 TCP_PORT = 54201 # 本节点 TCP 监听端口,随心跳一起告知对方 def make_hello_packet(): return json.dumps({ "type": "hello", # 消息类型:上线广播 "name": MY_NAME, "tcp_port": TCP_PORT }).encode("utf-8") # 创建 UDP socket udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # 必须开广播权限 udp_sock.bind(("", UDP_PORT)) # 绑定本机 UDP_PORT,用于接收单播回复 # 上线时向全网广播 hello udp_sock.sendto(make_hello_packet(), (BROADCAST_ADDR, UDP_PORT)) print(f"[{MY_NAME}] 已发送上线广播,正在等待其他节点响应...")

这段代码要理解两个关键点:一是setsockopt(SOL_SOCKET, SO_BROADCAST, 1)这行是在打开发送广播报文的权限,在很多 Linux 发行版上不写这行,sendto到广播地址会直接抛PermissionError;二是bind(("", UDP_PORT))是把自己绑定到本机的 54200 端口,这样别的节点通过sendto(..., ("本机IP", UDP_PORT))单播回来时,你的 socket 能收到。广播只能由“发包方”发出,收包方不需要也不能对广播地址做 bind,bind 的是自己的固定端口。

接收端要一个持续收包的循环,收到“别人上线”的广播后,要单播回复自己的信息,而不是以广播方式回复:

def get_local_ip(): # 建一个 UDP 连接,用 getsockname 拿本机出口 IP,实测最稳 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(("8.8.8.8", 80)) ip = s.getsockname()[0] finally: s.close() return ip def on_recv_hello(data, addr): """收到新节点的 hello 广播后,单播回复自己的信息""" peer_info = json.loads(data.decode("utf-8")) print(f"[发现] 新节点上线: {peer_info['name']} @ {addr[0]}:{peer_info['tcp_port']}") reply = json.dumps({ "type": "hello_reply", # 响应类型 "name": MY_NAME, "ip": get_local_ip(), # 本机可被连回的 IP(重点) "tcp_port": TCP_PORT }).encode("utf-8") # 注意这里发回的是 addr[0](新节点的 IP),不是 255.255.255.255 udp_sock.sendto(reply, (addr[0], UDP_PORT)) while True: data, addr = udp_sock.recvfrom(4096) if data: on_recv_hello(data, addr)

这里的逻辑顺序很重要:A 广播“我上线了”,B、C、D 各自收到后,回复的目的地址是addr[0](A 的 IP),而不是广播地址。如果 B 也广播回复,A 会收到大量重复的在线信息,而且 C、D 也会无关地收到 B 的回复,浪费带宽——这是很多人第一版代码里最常见的问题。get_local_ip()这个函数拿到的是本机出口 IP,也就是别人连通你时实际使用的 IP。如果机器有多个网卡,不能直接填127.0.0.1localhost,否则别人能看到你在线,但连不上你的 TCP 端口。

3.2 心跳、离开通知与在线列表:三个关键参数

广播只是上线时的“一次性发现”。之后怎么维持在线状态?常见做法是“心跳机制”:每个节点定期向所有已知在线节点单播一条hello(可以复用上线时的数据结构),收到任何消息都会刷新该节点的last_seen时间。这里有三组参数决定了系统的行为,我直接把建议值列出来:

参数建议值说明
HEARTBEAT_INTERVAL3 秒每 3 秒向在线列表单播一次心跳
TIMEOUT_FACTOR3 倍连续 3 个周期没收到心跳,判离线
LIST_CLEAN_INTERVAL3 秒定时清理超时节点的间隔

为什么是 3 秒、3 倍而不是 1 秒、2 倍?1 秒心跳会让 50 台机器之间每秒产生 50 条单播,虽然还没到拥堵的程度,但这笔无谓的开销完全可以省掉;3 秒心跳在轮询清理时,离线节点的消失延迟是 9 秒,对即时通信的体验来说已经是可感知的,如果你希望“退出”反馈更及时,可以额外加一条bye消息来立即通知。也就是说:bye负责“优雅下线”,心跳超时负责“异常掉线兜底”。清理逻辑可以做得很轻量,关键是判断条件要把 “收到任何消息” 都视为存活,不止是心跳——对方发来聊天消息同样能证明它在线,这样在线判断不会因为恰好错过心跳而误杀。

3.3 广播到底发给谁:255.255.255.255 与子网定向广播的差别

这里有一个很多人只在课设里碰到一次的坑:255.255.255.255并不总是能到达目标机器。全局广播地址只能送达“本子网”,它是受限广播,路由器默认不转发;而且在一台有多个网络接口的机器上,用255.255.255.255发包时,系统选择哪个接口、发到哪个网段并不受你控制。如果两台机器虽然在同一个局域网,但处在不同的广播域(比如分了 VLAN、或者一个接了路由器),全局广播就直接失效。

更稳妥的做法是使用“子网定向广播地址”:比如你的网卡 IP 是192.168.1.100,子网掩码是255.255.255.0,那么定向广播地址就是192.168.1.255。发到这个地址,只会送达192.168.1.0/24这个子网。确定方法很简单:查看本机 IP 和掩码,算出子网广播地址。Linux 用ip addr,Windows 用ipconfig,看到一个网段形如192.168.x.y时,把主机位全置 1 就是广播地址。

我一般会在配置里保留一个BROADCAST_ADDR变量,在255.255.255.255和定向广播之间可切换。如果发现对方收不到广播,第一件事就是把广播地址改成本机IP前三位 + .255试试。还有一个最笨但最可靠的兜底方案:如果你连对方的子网都不知道,就直接遍历扫描可能的网段,对192.168.0.0192.168.255.255的所有 IP 单播hello——代价是慢,但课设环境的网络规模足够小,扫描可接受。

4. 点对点消息通道:用 TCP 把“在线列表”变成“能聊天的对话框”

在线发现解决的是“谁能连”,消息收发解决的是“怎么连”。这一章从协议定义开始,再落到线程模型,最后处理 TCP 最容易踩的粘包半包问题。

4.1 先定消息协议再写 socket:JSON + 换行分隔

动手写 socket 之前,先把双方都认的消息格式定下来,否则收发双方各写各的解析,调试起来痛不欲生。我用的协议非常简单:每一条消息是一个 JSON 对象,对象序列化后以\n结尾。用 JSON 因为可读性好,出问题可以直接打印出来看;用\n分隔是因为它是 TCP 字节流里最容易实现的“消息边界”。协议字段如下:

字段类型说明
midstring消息唯一 ID,用于去重和确认
typestringchat聊天 /ack确认 /bye下线
fromstring发送方用户名
tostring接收方用户名
contentstring消息文本
tsnumber发送时间戳

mid是很重要的一步,很多新手图省事不设,结果对方因网络重传收到两条相同消息,没法去重。生成方式直接用uuid4()就行。封装编码解码的代码:

import json import uuid MSG_TERMINATOR = b"\n" def encode_msg(msg_type, sender, receiver, content): """把业务字段封装成带分隔符的字节流""" msg = { "mid": str(uuid.uuid4()), # 每一条消息独立 ID,防重复 "type": msg_type, "from": sender, "to": receiver, "content": content, "ts": int(time.time()) } return json.dumps(msg, ensure_ascii=False).encode("utf-8") + MSG_TERMINATOR

编码好之后,收发两端约定:读端永远“按换行切分,切出来的每一行 parse 一次 JSON”。这比自定义二进制包头简单得多,也足够应付课设和实际小型局域网工具。ensure_ascii=False这行别删,否则中文消息会被转成\uXXXX,可读性瞬间消失。

4.2 多连接与线程模型:每连接一个 reader 线程,所有写加锁

TCP 消息通道的代码分两块:监听端(每台机器都要监听,才能被动接收消息)和连接端(需要主动给某个节点发消息时 connect)。监听端用一个线程循环accept,每来一个连接就开一个 reader 线程处理:

import threading import socket TCP_PORT = 54201 tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) tcp_sock.bind(("", TCP_PORT)) tcp_sock.listen(16) # 同一时刻最多排队 16 个连接请求 def tcp_accept_loop(): """在主线程之外启动,负责接受新的 TCP 连接""" while True: conn, addr = tcp_sock.accept() # 每个连接独立线程,read 完一条消息就回调处理 threading.Thread(target=conn_reader, args=(conn,), daemon=True).start() def conn_reader(conn): """从连接里按行读,解决半包/粘包问题""" buf = b"" while True: chunk = conn.recv(4096) if not chunk: break # 对端关闭连接 buf += chunk while MSG_TERMINATOR in buf: line, buf = buf.split(MSG_TERMINATOR, 1) if not line.strip(): continue msg = json.loads(line.decode("utf-8")) handle_message(msg) # 业务函数:打印、入队、上屏等 conn.close()

这里最关键的是conn_reader里那个内层while:TCP 是字节流,一次recv(4096)的结果可能是半条消息、一条、或多条黏在一起。不加处理直接json.loads会随机报错。这个按分隔符切分的写法,配合buf += chunk累积,能同时处理“半包(一次 recv 不够一条消息)”和“粘包(一次 recv 包含多条消息)”两种情况,正确性上和一次 recv 一处理是完全不同的量级。

发送端的代码同样要考虑并发。如果你有多个线程可能向同一个 TCP 连接写数据(例如心跳线程和聊天发送线程同时操作同一个 socket),必须给写操作加锁,否则两个线程的sendall交错,对端会收到污染后的字节流,一整条 JSON 都解析失败:

WRITE_LOCK = threading.Lock() def send_msg(conn, msg_dict): """向指定连接发送消息,conn 可能是任意一端的 socket""" payload = json.dumps(msg_dict, ensure_ascii=False).encode("utf-8") + MSG_TERMINATOR # 所有写操作统一走这把锁,避免多线程 sendall 交错 with WRITE_LOCK: conn.sendall(payload)

对消息发送方,还要注意conn的归属:如果 A 主动连接 B,A 拿到的是主动connect回来的 socket;如果 A 被动接受 B 的连接,A 拿到的是accept返回的 socket。你需要在维护在线列表时把“节点 → socket”的映射关系建好,最简单的方式是Dict[peer_username, socket],并在连接建立和关闭时增删。

4.3 两个必须处理的时序问题:粘包与半包

这一节单独拎出来,是因为它通常是系统从“能跑”到“稳定”的分水岭。现象一模一样:收发少量短消息一切正常,连续发几十条后json.loads偶发JSONDecodeError,而且报错的位置不固定,纯粹看运气。

原因前面说了:TCP 不保边界。你recv到的数据量取决于网络分片、对端发送节奏和接收缓冲区状态,和你调用sendall的次数没有关系。如果你把代码写成:

data = conn.recv(4096) msg = json.loads(data) # 错!data 可能是多条消息拼一起,也可能是半条

这种写法在“快速连续发送”场景下必翻车。

正确思路是:把接收端当成一个“按行读取器”。攒一个缓冲区buf,每次 recv 后先追加上去,然后循环查\n是否存在,存在就切出一行处理,直到缓冲区里没有完整行才继续 recv。这就是上面conn_reader里那几行做的事。为了应对超大消息(比如有人直接粘贴几万字文本),可以给“单条消息最大长度”设一个上限,比如 64KB,超过就断开连接,防止你的缓冲区无限增长占满内存。这是生产环境里一定会加的保护,课设里写上这一句,答辩时也是加分项。

5. 计网课设避坑指南:五个最容易翻车的细节

这一章是血泪经验汇总,每一条都是我先踩过、后来帮同学排查时反复看到的“常规操作”。遇到问题别急着怀疑代码逻辑,先对照这几条检查环境。

5.1 防火墙静默丢包:代码没错,就是收不到包

现象:两台机器上代码一模一样,运行都没报错,但 A 广播后 B 什么都收不到,recvfrom一直阻塞。在 B 上抓包,发现 B 的网卡根本没收到 A 发的 UDP 报文。

原因:Windows 防火墙默认阻止陌生程序监听入站 UDP 端口。A 发出来的广播到达 B 的网卡后,被 Windows 过滤掉了,B 的 socket 连数据都没看到。开发时最容易忽略,因为本机自己跟自己通信时不受影响。

解决:在 Windows 上为程序放行端口,管理员权限下执行:

netsh advfirewall firewall add rule name="p2p-chat-udp" dir=in action=allow protocol=UDP localport=54200 netsh advfirewall firewall add rule name="p2p-chat-tcp" dir=in action=allow protocol=TCP localport=54201

如果是 Linux,检查ufwfirewalld是否启动。演示环境下图省事直接关防火墙也可以,但答辩时建议保留规则并展示你理解这一步的作用。

5.2 广播地址选错:跨子网后 255.255.255.255 不可达

现象:两台电脑明明都在同一个 WiFi 下,都能 ping 通对方的 IP,广播发现就是失败。单独拿另一台电脑试又成功,搞得像玄学。

原因:这个 WiFi 环境下客户端的子网掩码不是255.255.255.0,或者路由器开了 AP 隔离(无线客户端互相隔离),广播报文直接被丢弃。还有一种情况:本机有多个网卡(比如 VMware 虚拟网卡 + 无线网卡),系统选择路由时把广播发到了虚拟网卡所在的网段,真实目标机收不到。

解决:先用ipconfigip addr确认目标机器所在网段和本机的接口列表,把BROADCAST_ADDR255.255.255.255改成子网定向广播(例如192.168.1.255),并且在所有网卡接口都尝试发送一次。如果开了 AP 隔离,广播方案在此环境根本不可用,只能改用“遍历 /24 网段、逐个单播 hello”的方式。课设演示时建议提前在演示环境测试广播,不要到现场才发现网络策略不允许。

5.3 TCP 粘包或半包,json.loads 随机报错

现象:消息收发功能正常,但高频连续发消息时,界面偶尔弹 JSON 解析错误,且错误内容时有时无,极难复现。

原因:就是第 4.3 节说的,recv拿到的数据不是按消息边界对齐的。很多人会下意识觉得是自己的消息格式不对,其实格式一点问题没有,是接收逻辑没做边界处理。

解决:把接收端改成“缓冲 + 按行切分”的统一模式。不要单独为某一条大消息写特殊解析逻辑,所有消息都走同一个拆包函数。拆包函数里遇到不完整行就留着,等下一个chunk到达后续接,见 4.2 节的conn_reader。改完之后连续发几百条压力测试,问题应当消失。

5.4 心跳线程和 GUI 线程抢在线列表,界面抖动

现象:在线列表偶尔闪一下、排序变来变去;稍微加大心跳频率后,界面直接无响应。

原因:心跳收包线程在修改在线列表数据(增删节点),GUI 主线程同时在读列表渲染界面。两个线程同时操作同一个 Python 列表或字典,出现竞态,轻则显示错乱,重则界面卡死。

解决:一条规矩——所有对在线列表的修改都在 GUI 线程做。监听线程收到消息后,不直接改列表,而是把“事件”放进一个queue.Queue,GUI 主线程每 100ms 轮询一次队列并更新列表。用queue的好处是线程安全,不需要自己加锁就能把数据从网络线程传递给界面线程。

5.5 大消息传输把主线程卡死,UI 假死

现象:点一个几 MB 的文件发送,窗口立刻无响应,任务管理器显示进程 CPU 占满,过一会儿连接也被断开。

原因:你把sendall直接放在了 GUI 主线程里。sendall要等数据进内核缓冲区并确认对端接收,大文件传输期间主线程阻塞,整个窗口失去响应;同时接收端误以为对端异常,超时断开。

解决:网络发送一律放子线程,GUI 进程只负责发起“发送”命令,不做实际的sendall。如果是文件传输,建议单独开一个文件通道,不要复用聊天消息的 JSON 流——文件没有按行切分的语义,需要的是“先发文件名和大小,再发原始字节,最后发结束标记”的流程。其中文件内容分段读、分段发(例如每次读 64KB),不要在内存里把整个文件读成字节再一次性sendall。课设阶段要是没时间做完整文件传输,可以直接在 UI 层限制“仅支持文本消息”,比做一半翻车强。

6. 答辩现场如何演示:从本机双开到 Wireshark 抓包自证

代码跑通只是第一步,答辩现场要让老师快速相信“这确实是 P2P 架构”,最有效的办法是用 Wireshark 抓到三条证据:UDP 广播在哪里、TCP 连接是谁和谁建立的、消息有没有经过第三台机器。按下面这个流程准备演示,二十分钟就能完成。

6.1 三种演示环境的搭建

本机双开是最低成本的验证方式。同一台机器上跑两个进程,一个绑定在 54200/54201,另一个需要避开端口冲突:Linux 上给 UDP 和 TCP socket 都加上SO_REUSEPORT后,两个进程可以绑定相同端口;Windows 上SO_REUSEADDR通常可行。如果嫌麻烦,可以给第二个实例设一个偏移端口,比如用 54210,然后让广播地址还是指向本机 IP。注意两个进程的get_local_ip()返回的可能是127.0.0.1或本机 IP,只要确保 TCP 端口在监听,互连就能成功。

双机验证是答辩的标准形态。两台电脑连同一个路由器或交换机,先互相 ping 通,然后分别在两台机器上启动程序,观察两边的在线列表是否出现对方。VMware 或 VirtualBox 的 Host-Only 网络也能模拟,但要注意虚拟网卡的 IP 段和宿主机不一样,广播地址要按虚拟网卡的网段来配置,这正好能体现你对第 3.3 节“定向广播”的理解。

6.2 Wireshark 里的三处观察点

启动 Wireshark,抓一下演示过程中产生的流量,然后用三条过滤语句分别引导老师看:

观察点过滤语句应该看到什么
UDP 发现包udp.port eq 54200启动时一条广播 hello,随后周期性单播心跳
TCP 三次握手tcp.port eq 54201两个 IP 之间的 SYN / SYN-ACK / ACK 序列
消息内容直传tcp.contains "mid"聊天内容出现在对话双方的 IP 之间,没有第三个 IP 参与转发

看到“消息内容的源 IP 和目标 IP 就是聊天双方”,胜过你在答辩时用十句话解释“我的架构是 P2P”。反过来,如果你看到消息经过了第三台机器(源或者目标是另一个 IP),说明你的实现还是 C/S,老师一眼就能看穿。

6.3 加一个让答辩老师点头的细节:断线检测演示

在演示里加一个“拔线实验”:A 和 B 都在线时,直接断开 B 的网线或关闭 B 的进程,然后盯住 A 的在线列表。正常配置下(心跳 3 秒、超时 3 倍),9 秒后 B 会从 A 的列表里消失,界面显示“节点已离线”。把事先截好的前后对比图放进答辩 PPT,工程完整性立刻上一个台阶。

我做这个课设时,最深的教训是:一开始把“发现”和“聊天”写在了同一个 socket 收发逻辑里,结果广播包和聊天包混在一起,解析逻辑越改越乱。后来的经验是,两个通道彻底分开,UDP 只管“谁在”,TCP 只管“聊什么”,从设计上消灭了那一类问题。这也是这节课设真正要锻炼的能力:不是写多少行代码,而是能不能在一开始就把架构划分清楚。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询