实验描述
本编程作业的题目描述:
在这个编程作业中,你将用Python编写一个客户ping程序。该客户将发送一个简单的ping报文,接受一个从服务器返回的ping报文,并确定从该客户发送ping报文到接收到ping报文为止的时延。该时延称为往返时延(RTT)。由该客户和服务器提供的功能类似于在现代操作系统中可用的标准ping程序,然而,标准的ping使用互联网控制报文协议(ICMP)(我们将在第4章中学习ICMP)。此时我们将创建一个非标准(但简单)的基于UDP的ping程序。
你的ping程序经UDP向目标服务器发送10个ping报文,对于每个报文,当对应的ping报文返回时,你的客户要确定和打印RTT。因为UDP是一个不可靠协议,由客户发送的分组可能会丢失。为此,客户不能无限期地等待对ping报文的回答。客户等待服务器回答的时间至多为1秒;如果没有收到回答,客户假定该分组丢失并相应地打印一条报文。
在此作业中,我们给出服务器的完整代码(在配套网站中可以找到。你的任务是编写客户代码,该代码与服务器代码非常类似。建议你先仔细学习服务器的代码,然后编写你的客户代码,可以不受限制地从服务器代码中剪贴代码行。
python编写的 使用UDP套接字 跟客户端相连的服务器代码:
# UDPPingerServer.py
# We will need the following module to generate randomized lost packets import random
from socket import *
import random
# Create a UDP socket
# Notice the use of SOCK_DGRAM for UDP packets
serverSocket = socket(AF_INET, SOCK_DGRAM)
# Assign IP address and port number to socket
serverSocket.bind(('', 1234)) # 这里的端口号随便取,我就把这里改成1234了
while True:
# Generate random number in the range of 0 to 10
rand = random.randint(0, 10)
# Receive the client packet along with the address it is coming from
message, address = serverSocket.recvfrom(1024)
# Capitalize the message from the client
message = message.upper()
# If rand is less is than 4, we consider the packet lost and do not respond
if rand < 4:
continue
# Otherwise, the server responds
serverSocket.sendto(message, address)
python编写的 使用UDP套接字 用于发送数据包给服务器的客户端代码:
注意:服务器地址直接使用本机localhost(对应的IP地址为:127.0.0.1),
让本地主机既充当客户机又充当服务器,才可以直接在cmd中出运行结果。
# UDPPingerClient.py
from socket import *
import time
serverName = '127.0.0.1' # 服务器地址,本例中使用本地主机
serverPort = 1234 # 服务器指定的端口
clientSocket = socket(AF_INET, SOCK_DGRAM) # 创建一个UDP套接字
clientSocket.settimeout(1) # 设置套接字超时值为1s
LostDataCnt = 0 # 计算丢包次数
for i in range(0,10):
sendTime = time.time()# 记录下开始发送的时间
message = ('Ping %d %s' % (i+1,sendTime)).encode() # 生成数据报,编码为bytes以便发送
try:
clientSocket.sendto(message,(serverName,serverPort)) # 将信息发送到服务器
modifiedMessage,serverAddress = clientSocket.recvfrom(1024) # 接收服务器返回的数据
rtt = time.time() - sendTime # 服务器返回时间 - 客户机发送时间 = 一次往返时间RTT
print('客户机发送的数据包编号: %d\n返回数据的服务器名称: %s\n往返时间: %.3fs' % (i+1,serverName,rtt))
except Exception as e:
print('客户机发送的数据包编号: %d\n请求超时' % (i+1))
LostDataCnt += 1
print('十次请求中丢包的次数为: %d\n' % (LostDataCnt))
clientSocket.close() # 关闭套接字
运行效果:
启动服务器:
py UDPPingerServer.py
启动客户机:
python UDPPingServer.py
可选练习【待完成】
- 目前,程序计算每个数据包的往返时间(RTT),并单独打印出来。请按照标准ping程序的模式修改。您需要在客户端每次ping后显示最小,最大和平均RTT。另外,还需计算丢包率(百分比)。
- UDP Ping的另一个类似的应用是UDP Heartbeat。心跳可用于检查应用程序是否已启动并运行,并报告单向丢包。客户端在UDP数据包中将一个序列号和当前时间戳发送给正在监听客户端心跳的服务器。服务器收到数据包后,计算时差,报告丢包(若发生)。如果心跳数据包在指定的一段时间内丢失,我们可以假设客户端应用程序已经停止。实现UDP Heartbeat(客户端和服务器端)。您需要修改给定的UDPPingerServer.py和您自己的UDP ping客户端。
参考资料:
https://github.com/moranzcw/Computer-Networking-A-Top-Down-Approach-NOTES