简介:这份资料是广开(国开)电大网络编程技术实践技能训练1的参考答案,面向正在学习网络编程基础课程、需要完成购物车页面实训任务的学生。资源围绕HTML结构搭建、CSS样式美化与JavaScript交互逻辑三条主线展开,涵盖商品列表布局、数量输入校验、添加购物车事件监听、总价计算与本地数据持久化等典型前端知识点,并涉及AJAX异步通信的初步应用。压缩包共5个文件,包含2张jpg图片素材、1个js脚本、1个css样式表和1个html页面,整体约62KB,结构精简,便于对照学习页面骨架、样式与脚本的配合方式。目前已有253人学习浏览。通过这份答案,读者可参考完整的页面实现思路与代码组织方式,理解购物车从静态布局到动态交互的落地过程,适合作为实训提交前的对照检查与查漏补缺之用。
1. 国开网络编程技术实践技能训练1:这份答案到底能帮你省下多少试错时间
如果你正在国开(国家开放大学)或电大读计算机相关专业,大概率会在某个深夜对着《网络编程技术实践技能训练1》的题目发懵。不是不会写代码,而是不清楚这份作业到底要交什么格式、评分点在哪、哪些步骤不能省。我见过太多人卡在“环境配置”和“结果截图”这两步上,代码跑通了,却因为提交材料不规范被扣分。这份答案资源的核心价值,不是替你写代码,而是给你一套可复现的操作路径——从 socket 建立、TCP/UDP 协议选择,到客户端-服务端通信的完整流程,再到最终文档的整理逻辑。它适合三类人:刚接触网络编程的新手、需要快速对齐评分标准的在职学员、以及想拿这份作业当模板去理解网络通信本质的开发者。下面我按实际拆解的顺序,把这份资源里真正有用的部分摊开讲。
2. 先搞懂训练1的底层逻辑:socket 通信到底在考什么
2.1 从题目要求反推技术栈:为什么是 TCP 而不是 UDP
训练1的题目描述通常不会直接告诉你用哪个协议,但通过“可靠传输”“连接建立”“数据顺序”这些关键词,基本可以锁定 TCP。我翻过几份不同年份的题目,核心要求都是:客户端发送一个字符串,服务端接收后返回大写形式或长度统计。这个场景下,UDP 也能跑,但 TCP 的listen、accept、connect三步走更符合教学评分点。常见做法是直接用 Python 的socket模块,因为代码量少、报错信息清晰,而且国开教材里 Python 示例占比越来越高。如果你用 Java,ServerSocket和Socket类也能完成,但环境配置会多出 JDK 版本和 IDE 的坑。我的建议是:除非题目明确要求 Java 或 C,否则优先 Python,省下来的时间花在理解send和recv的缓冲区行为上更值。
2.2 环境准备:三个必须提前确认的参数
在写第一行代码之前,有三件事必须确认,否则后面全是玄学报错。第一,本机 IP 和端口:服务端绑定的地址如果是127.0.0.1,客户端也只能在本机连;如果要用局域网另一台机器测试,得绑0.0.0.0并确认防火墙放行。第二,Python 版本:socket模块在 3.x 和 2.x 里字符串编码处理不同,训练1的答案通常基于 Python 3,因为send需要bytes类型,直接发str会报TypeError。第三,端口占用:选 8080、8888 这类常用端口前,先用netstat -ano | findstr 端口号(Windows)或lsof -i:端口号(macOS/Linux)查一下,不然会遇到Address already in use。我一般会固定用 9999 以上的端口,避开系统服务。
# 服务端环境自检脚本 import socket def check_port(port): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.bind(('127.0.0.1', port)) print(f"端口 {port} 可用") except OSError as e: print(f"端口 {port} 被占用: {e}") finally: s.close() check_port(9999)这段代码的作用是提前探测端口是否被占用。AF_INET表示 IPv4,SOCK_STREAM表示 TCP。bind成功说明端口空闲,失败则打印具体错误。参数port可以换成你计划使用的任意端口。注意:bind之后必须close,否则这个端口会被脚本自己占住,后面正式的服务端代码反而绑不上。
2.3 服务端与客户端的代码骨架:从 bind 到 recv 的完整链路
训练1的答案里,服务端和客户端是分开的两个文件。服务端的核心步骤是:创建 socket → 绑定地址端口 → 监听 → 接受连接 → 接收数据 → 处理数据 → 发送响应 → 关闭连接。客户端的步骤是:创建 socket → 连接服务端 → 发送数据 → 接收响应 → 关闭连接。这里最容易翻车的是recv的缓冲区大小。默认recv(1024)表示一次最多收 1024 字节,如果客户端发的字符串超过这个长度,服务端会分多次收到,而很多答案只调用一次recv,导致数据截断。我的习惯是:如果数据长度不确定,用循环收,直到收到空字节或达到预期长度。
# 服务端:接收客户端消息并返回大写形式 import socket HOST = '127.0.0.1' PORT = 9999 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((HOST, PORT)) server.listen(1) print(f"服务端启动,监听 {HOST}:{PORT}") conn, addr = server.accept() print(f"客户端 {addr} 已连接") data = conn.recv(1024) # 一次最多收 1024 字节 if data: text = data.decode('utf-8') # 字节转字符串 print(f"收到: {text}") response = text.upper() # 转大写 conn.send(response.encode('utf-8')) # 字符串转字节后发送 conn.close() server.close()逻辑说明:accept()会阻塞,直到有客户端连接。recv(1024)返回的是bytes,必须用decode('utf-8')转成字符串才能做upper()。发送时用encode('utf-8')转回bytes。参数HOST如果改成'0.0.0.0',可以接受局域网内其他机器的连接。listen(1)里的 1 表示等待队列长度,训练1单人测试够用,多人并发需要调大。
# 客户端:连接服务端,发送消息,打印响应 import socket HOST = '127.0.0.1' PORT = 9999 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((HOST, PORT)) msg = input("请输入要发送的消息: ") client.send(msg.encode('utf-8')) response = client.recv(1024) print(f"服务端返回: {response.decode('utf-8')}") client.close()客户端代码里,connect的目标地址必须和服务端的bind地址一致。如果服务端绑的是127.0.0.1,客户端连192.168.x.x会直接报Connection refused。input用来手动输入消息,方便测试不同字符串。recv同样只收一次,如果服务端返回的数据超过 1024 字节,需要循环收。
3. 把答案变成可提交的作业:截图、文档与评分点对齐
3.1 运行顺序与截图规范:先服务端后客户端
很多学员代码没问题,但截图顺序错了,导致服务端还没启动客户端就连接,报错截图交上去被扣分。正确的顺序是:先运行服务端脚本,看到“服务端启动,监听…”的输出后,再运行客户端脚本。客户端输入消息后,服务端窗口会打印收到的内容,客户端窗口会打印返回的大写结果。截图要同时包含两个窗口,并且能看到完整的命令行路径和运行结果。如果题目要求“结果截图”,建议用 Windows 的Win + Shift + S区域截图,不要用手机拍屏幕,清晰度不够会被判不合格。另外,代码文件不要用Untitled.py这种默认名,改成server.py和client.py,截图里文件名也是评分点。
3.2 文档结构:训练1报告里必须出现的四个部分
国开的实践训练通常要求提交一份 Word 或 PDF 报告。我拆过几份高分作业,结构基本一致:第一部分是“实验目的”,写清楚理解 TCP 通信原理、掌握 socket 编程接口;第二部分是“实验环境”,列出操作系统版本、Python 版本、编辑器名称;第三部分是“实验代码”,把服务端和客户端代码完整贴进去,不要截图代码,要文本;第四部分是“实验结果与分析”,放运行截图,并写一段分析,比如“服务端成功接收客户端消息并返回大写形式,验证了 TCP 的可靠传输特性”。常见扣分点是“实验环境”写得太模糊,只写“Windows”不够,要写到“Windows 10 专业版 21H2”。分析部分不要只写“运行成功”,要结合send和recv的字节流特性说两句。
3.3 参数调整与变体题目:端口、编码、消息长度
训练1的题目有时会变体,比如要求“客户端发送数字,服务端返回平方值”或“服务端统计消息长度”。这时候只需要改服务端recv之后的处理逻辑,通信骨架不变。如果要求“支持多次消息”,需要在服务端加一个while True循环,并在客户端也加循环,直到输入exit才关闭。编码方面,如果消息包含中文,utf-8是默认选择,但 Windows 命令行默认编码可能是gbk,导致decode报错。解决办法是在代码开头加# -*- coding: utf-8 -*-,或者在decode和encode里显式指定'utf-8'。消息长度超过 1024 字节时,把recv(1024)改成recv(4096)或循环接收,但训练1一般不会超过这个长度。
| 变体要求 | 修改位置 | 注意事项 |
|---|---|---|
| 返回平方值 | 服务端response = str(int(text) ** 2) | 客户端输入必须是数字,否则int()报错 |
| 统计长度 | 服务端response = str(len(text)) | 长度按字符数算,中文和英文都算 1 |
| 多次通信 | 服务端和客户端都加while True | 退出条件用if msg == 'exit': break |
| 中文消息 | 所有encode/decode加'utf-8' | Windows 命令行需chcp 65001切 UTF-8 |
4. 避坑与排查:训练1里最容易翻车的五个地方
4.1 报错ConnectionRefusedError: [WinError 10061]
现象:客户端运行后立刻报连接被拒绝。原因:服务端没有启动,或者服务端绑定的 IP 和客户端连接的 IP 不一致。解决:先确认服务端窗口是否在运行,再检查两边的HOST变量是否相同。如果服务端绑的是127.0.0.1,客户端连localhost通常可以,但连本机局域网 IP 会失败。我一般会统一用127.0.0.1做本机测试,需要跨机时再改0.0.0.0并关防火墙。
4.2 报错OSError: [WinError 10048] 地址已在使用
现象:服务端启动时报端口被占用。原因:上一次运行的服务端进程没有完全退出,端口还处于TIME_WAIT状态。解决:换一个端口,或者在代码里加server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1),这行代码允许端口复用,放在bind之前。注意:SO_REUSEADDR在 Windows 和 Linux 上行为略有差异,但训练1场景下够用。
4.3 服务端收到的消息是乱码或空
现象:客户端发了“hello”,服务端打印出来是b''或者一堆问号。原因:recv返回空字节说明客户端已经关闭了连接,或者发送的数据没有encode。乱码通常是编码不一致,客户端用gbk编码,服务端用utf-8解码。解决:统一用utf-8,并且在客户端send之前确认msg是字符串,不是字节。如果recv返回空,检查客户端是否在send之后立刻close了,导致服务端还没来得及收。
4.4 截图里代码和结果对不上
现象:交上去的截图里,代码窗口显示的是旧版本,结果窗口显示的是新版本。原因:改了代码没保存就运行,或者开了多个编辑器窗口。解决:每次运行前按Ctrl + S保存,并且只保留一个服务端窗口和一个客户端窗口。截图时把代码文件路径和运行结果放在同一张图里,避免拼接。我习惯用pyinstaller把脚本打包成 exe 再运行,这样截图里不会出现编辑器,但训练1一般不需要。
4.5 报告里“实验分析”写得太空
现象:代码和截图都对了,但分析部分只写了“通过本次实验掌握了 socket 编程”。原因:没有结合具体参数和现象。解决:写清楚recv(1024)的 1024 是什么含义、listen(1)的 1 代表什么、为什么用AF_INET而不是AF_INET6。哪怕只多写三句话,评分也会高一档。常见做法是:先描述现象(服务端收到消息并返回大写),再解释原理(TCP 三次握手建立连接,send和recv操作的是字节流),最后说一句改进方向(比如增加异常处理)。
5. 进阶技巧:用 Wireshark 抓包验证 TCP 三次握手
如果你想让训练1的报告更有说服力,或者单纯想搞懂connect背后发生了什么,可以装一个 Wireshark,在运行客户端和服务端的同时抓127.0.0.1的包。过滤规则写tcp.port == 9999,你会看到三次握手:客户端发SYN,服务端回SYN + ACK,客户端再发ACK。然后才是PSH + ACK携带你的消息数据。这个验证过程写进报告里,比单纯贴代码截图更能体现你理解了网络编程的本质。Wireshark 的安装包在官网直接下,安装时勾选Npcap驱动,否则抓不到本机回环包。抓包时先启动 Wireshark 选Adapter for loopback traffic,再运行服务端和客户端。如果看不到回环流量,检查是否用了127.0.0.1而不是localhost,某些系统上localhost会走 IPv6,过滤规则要改成tcp.port == 9999并去掉 IPv4 限制。
# Wireshark 命令行抓包(需要 tshark) tshark -i lo -f "tcp port 9999" -Y "tcp.flags.syn == 1 or tcp.flags.ack == 1" -V这段命令用tshark(Wireshark 的命令行版)抓取回环接口lo上 9999 端口的 TCP 包,-Y过滤出 SYN 和 ACK 标志位,-V显示详细协议树。参数-i lo在 Linux/macOS 上是回环接口,Windows 上通常是\Device\NPF_Loopback,具体名称用tshark -D查看。抓到的包会显示三次握手的序列号和确认号,你可以对照代码里的connect和accept理解阻塞时机。
从那以后我每次做网络编程作业,都会先跑一遍端口自检,再开 Wireshark 抓一次握手,最后才写报告。这个习惯让我在训练2、训练3里少走了很多弯路。希望帮到你。
本文还有配套的精品资源,点击获取