当前位置: 首页 > news >正文

计算机网络第二章:作业 2: UDP ping 程序

套接字编程作业 2:UDP Ping 程序

问题描述:

在这个实验中,你将通过Python使用UDP套接字编程,编写一个ping程序。Ping程序是用来测试网络延迟的工具,客户端通过发送请求到服务器,然后计算往返时间(RTT),并处理可能的丢包。作业的主要任务是:

  1. 编写一个UDP客户端,向服务器发送10个ping请求。
  2. 服务器会根据收到的请求返回响应,但30%的请求会被随机丢弃以模拟丢包。
  3. 客户端应处理超时情况,超时阈值为1秒。
  4. 每次ping请求后,客户端应输出收到的响应或超时消息,并显示往返时间(RTT)。

你需要实现的客户端程序功能类似于标准的ping命令,但使用的是UDP协议,而不是ICMP协议。

问题解决流程:

  1. 理解UDP协议的特点

    • UDP是一种无连接、轻量级但不可靠的传输协议,数据包可能会丢失,不保证数据的到达顺序。
    • 在Ping程序中,我们使用UDP,因为其简单且能模拟不可靠的网络通信。
  2. 服务器端实现

    • 我们提供了一个服务器端程序UDPPingerServer.py,它接收来自客户端的请求,随机丢弃30%的请求,剩下的请求则返回给客户端。
    • 你需要在本地或远程服务器上运行该服务器程序,然后实现客户端程序与其通信。
  3. 客户端功能要求

    • 使用UDP向服务器发送10次ping请求,每次请求中包含当前的发送时间。
    • 服务器返回响应后,计算该请求的往返时间(RTT)。
    • 如果请求超过1秒未收到响应,则显示"Request timed out"。
    • 最终输出每次ping的RTT或者超时消息。

步骤 1:服务器代码

服务器代码已经提供,先确保它在本地或远程服务器上运行。

# UDPPingerServer.py 
from socket import * 
import random# 创建一个UDP套接字
serverSocket = socket(AF_INET, SOCK_DGRAM)
# 绑定服务器的IP地址和端口号
serverSocket.bind(('', 12000))while True:# 生成一个随机数,用于模拟丢包rand = random.randint(0, 10)# 接收客户端消息和地址message, address = serverSocket.recvfrom(1024)# 将收到的消息转换为大写message = message.upper()# 如果随机数小于4,模拟丢包,不返回任何消息if rand < 4:continue# 否则,将消息返回给客户端serverSocket.sendto(message, address)
  • 该服务器程序使用UDP协议监听端口12000,并随机丢弃30%的客户端请求。

步骤 2:客户端代码

我们现在需要编写客户端程序,它将向服务器发送10个ping请求,并显示每次请求的结果,包括往返时间或超时。

import time
from socket import *# 创建UDP套接字
clientSocket = socket(AF_INET, SOCK_DGRAM)
# 设置超时时间为1秒
clientSocket.settimeout(1)# 服务器的地址和端口
serverName = 'localhost'  # 本地运行时使用 'localhost'
serverPort = 12000# 发送10次ping请求
for sequence_number in range(1, 11):# 获取当前时间戳sendTime = time.time()# 构造ping消息message = f'Ping {sequence_number} {sendTime}'try:# 向服务器发送消息clientSocket.sendto(message.encode(), (serverName, serverPort))# 等待服务器响应,超时1秒response, serverAddress = clientSocket.recvfrom(1024)# 计算RTTrtt = time.time() - sendTime# 打印服务器返回的消息和RTTprint(f'Received from server: {response.decode()} RTT = {rtt:.4f} seconds')except timeout:# 超时处理print('Request timed out')# 关闭套接字
clientSocket.close()

代码解析:

  1. 创建UDP套接字clientSocket = socket(AF_INET, SOCK_DGRAM) 使用UDP协议,适合无连接的通信。
  2. 设置超时clientSocket.settimeout(1) 设置接收数据包的超时时间为1秒,如果在1秒内未收到响应,则抛出timeout异常。
  3. 发送ping消息clientSocket.sendto(message.encode(), (serverName, serverPort)) 向服务器发送包含序列号和时间戳的ping消息。
  4. 接收服务器响应clientSocket.recvfrom(1024) 接收服务器返回的消息,并计算消息的往返时间(RTT)。
  5. 超时处理:如果未收到响应,客户端会输出“Request timed out”。

步骤 3:运行程序

1. 运行服务器:

在本地或远程服务器上运行提供的服务器代码:

python UDPPingerServer.py
2. 运行客户端:

在另一个终端窗口中运行客户端代码:

python UDPPingerClient.py

你会看到客户端向服务器发送10次ping请求的输出,类似于以下结果:

Received from server: PING 1 1663261625.64255 RTT = 0.0021 seconds
Received from server: PING 2 1663261626.64305 RTT = 0.0020 seconds
Request timed out
Received from server: PING 4 1663261628.64400 RTT = 0.0021 seconds
...
  • 如果服务器丢弃了请求,客户端会显示Request timed out
  • 如果服务器返回了响应,客户端会显示往返时间(RTT)。

可选练习1

客户端程序需要在发送10次Ping请求后计算最小、最大和平均RTT,同时计算丢包率。我们可以通过保存每次Ping的RTT值,最后计算这些统计数据。具体步骤如下:

实现步骤

  1. 存储每次Ping的RTT:为RTT创建一个列表,每次接收到响应时,将RTT添加到该列表中。
  2. 统计丢包情况:为超时次数创建一个计数器,每次超时时递增。
  3. 计算最小、最大和平均RTT:在发送完所有Ping请求后,通过列表计算最小值、最大值和平均值。
  4. 计算丢包率:丢包率 = (丢失的包数 / 总包数)× 100%。

修改后的代码

import time
from socket import *# 创建UDP套接字
clientSocket = socket(AF_INET, SOCK_DGRAM)
# 设置超时时间为1秒
clientSocket.settimeout(1)# 服务器的地址和端口
serverName = 'localhost'  # 本地运行时使用 'localhost'
serverPort = 12000# 初始化变量
rtt_list = []  # 存储每次成功Ping的RTT
timeout_count = 0  # 记录超时的次数
total_pings = 10  # 发送的Ping总次数# 发送10次ping请求
for sequence_number in range(1, total_pings + 1):# 获取当前时间戳sendTime = time.time()# 构造ping消息message = f'Ping {sequence_number} {sendTime}'try:# 向服务器发送消息clientSocket.sendto(message.encode(), (serverName, serverPort))# 等待服务器响应,超时1秒response, serverAddress = clientSocket.recvfrom(1024)# 计算RTTrtt = time.time() - sendTimertt_list.append(rtt)  # 将RTT加入列表# 打印服务器返回的消息和RTTprint(f'Received from server: {response.decode()} RTT = {rtt:.4f} seconds')except timeout:# 超时处理,计数器增加print('Request timed out')timeout_count += 1# 关闭套接字
clientSocket.close()# 如果有成功的Ping,则计算最小、最大和平均RTT
if rtt_list:min_rtt = min(rtt_list)max_rtt = max(rtt_list)avg_rtt = sum(rtt_list) / len(rtt_list)print(f'\n--- Ping statistics ---')print(f'{total_pings} packets transmitted, {len(rtt_list)} packets received, 'f'{timeout_count / total_pings * 100:.1f}% packet loss')print(f'rtt min/avg/max = {min_rtt:.4f}/{avg_rtt:.4f}/{max_rtt:.4f} seconds')else:print(f'\n--- Ping statistics ---')print(f'{total_pings} packets transmitted, 0 packets received, 100.0% packet loss')

代码解析

  1. rtt_list:这是一个列表,用于存储每次成功的RTT值。当接收到响应时,将RTT值添加到该列表中。
  2. timeout_count:这是一个计数器,用于记录超时(丢包)的次数。每当请求超时时,计数器会加1。
  3. RTT计算:程序结束后,检查rtt_list是否为空。如果有接收到的Ping响应,则计算最小、最大和平均RTT,并打印出来。
  4. 丢包率计算:丢包率通过timeout_count / total_pings * 100计算,表示为百分比形式。

输出示例

假设服务器响应如下:

Received from server: PING 1 1663261625.64255 RTT = 0.0021 seconds
Request timed out
Received from server: PING 3 1663261626.64305 RTT = 0.0020 seconds
Request timed out
Received from server: PING 5 1663261627.64400 RTT = 0.0021 seconds
...--- Ping statistics ---
10 packets transmitted, 6 packets received, 40.0% packet loss
rtt min/avg/max = 0.0020/0.0021/0.0022 seconds

通过这些修改,客户端程序在完成所有Ping操作后,会输出最小、最大和平均RTT,并计算出丢包率。这种行为模拟了标准ping命令的功能,提供了更加详细的网络通信统计信息。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • JavaScript基础学习:预解析机制
  • 2024 RedisAnd Mysql基础与进阶操作系列(13)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
  • 螺栓与散装物体检测系统源码分享
  • idea生成类信息及快捷开发配置
  • PHP邮件发送教程:如何用PHP发送电子邮件?
  • SQLServer TOP(Transact-SQL)
  • 隨著 iOS 18 到來,AirPods Pro 2 解鎖移動頭部回應 Siri 功能
  • 【PyQt5】object属性
  • 2023年全国研究生数学建模竞赛华为杯B题DFT类矩阵的整数分解逼近求解全过程文档及程序
  • idea多模块启动
  • 【北京迅为】《STM32MP157开发板使用手册》- 第三十九章 消息队列实验
  • k8s常用指令续:
  • 避免死锁发生的策略
  • 240919-Pip先在线下载不安装+再离线安装
  • AI助力智慧农田作物病虫害监测,基于YOLOv8全系列【n/s/m/l/x】参数模型开发构建花田作物种植场景下棉花作物常见病虫害检测识别系统
  • Babel配置的不完全指南
  • Docker 笔记(2):Dockerfile
  • java8 Stream Pipelines 浅析
  • Linux gpio口使用方法
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 简单实现一个textarea自适应高度
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 力扣(LeetCode)56
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 深度解析利用ES6进行Promise封装总结
  • 深度学习在携程攻略社区的应用
  • 深入浅出Node.js
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • ​zookeeper集群配置与启动
  • ‌分布式计算技术与复杂算法优化:‌现代数据处理的基石
  • #13 yum、编译安装与sed命令的使用
  • #pragma data_seg 共享数据区(转)
  • #职场发展#其他
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第6节 (嵌套的Finally代码块)
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (转载)Google Chrome调试JS
  • .CSS-hover 的解释
  • .Net 8.0 新的变化
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .NET Core 中插件式开发实现
  • .net framework 4.0中如何 输出 form 的name属性。
  • .NET IoC 容器(三)Autofac
  • .NET Micro Framework 4.2 beta 源码探析
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .NET 反射的使用
  • .net 使用$.ajax实现从前台调用后台方法(包含静态方法和非静态方法调用)
  • .NET连接MongoDB数据库实例教程
  • .net通用权限框架B/S (三)--MODEL层(2)
  • []AT 指令 收发短信和GPRS上网 SIM508/548