《计算机网络自顶向下方法》第二章套接字编程作业——UDP Ping程序

目录

一、实验内容

二、实验代码 

三、实验结果

四、附加实验


一、实验内容

    在本实验中,您将学习使用Python进行UDP套接字编程的基础知识。您将学习如何使用UDP套接字发送和接收数据报,以及如何设置适当的套接字超时。在实验中,您将熟悉Ping应用程序及其在计算统计信息(如丢包率)中的作用。

    您首先需要研究一个用Python编写的简单的ping服务器程序,并实现对应的客户端程序。这些程序提供的功能类似于现代操作系统中可用的标准ping程序功能。然而,我们的程序使用更简单的UDP协议,而不是标准互联网控制消息协议(ICMP)来进行通信。 ping协议允许客户端机器发送一个数据包到远程机器,并使远程机器将数据包返回到客户(称为回显)的操作。另外,ping协议允许主机计算它到其他机器的往返时间。

具体来说,您的客户端程序应该

1. 使用UDP发送ping消息(注意:不同于TCP,您不需要首先建立连接,因为UDP是无连接协议。)
2. 从服务器输出响应消息
3. 如果从服务器受到响应,则计算并输出每个数据包的往返时延(RTT)(以秒为单位),
4. 否则输出“请求超时”

以下代码完整实现了一个ping服务器。您需要在运行客户端程序之前编译并运行此代码。*而且您不需要修改此代码。在这个服务器代码中,30%的客户端的数据包会被模拟丢失。你应该仔细研究这个代码,它将帮助你编写ping客户端。

# 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(('', 12000)) 

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) 

在开发过程中,您应该先在计算机上运行`UDPPingerServer.py`,并通过向`localhost`(或127.0.0.1)发送数据包来测试客户端。调试完成代码后,您应该能看到ping服务器和ping客户端在不同机器上通过网络进行通信。

本实验中的ping消息格式使用最简单的方式。客户端消息只有一行,由以下格式的ASCII字符组成:其中*sequence_number*从1开始,一直到10,共10条消息,而*time*则是客户端发送消息时的时间。
 

二、实验代码 

# UDPPingerclient.py

from socket import *
import time

# 定义ip地址和端口号
servername = '127.0.0.1'
serverport = 12000

# 创建一个UDP套接字
clientsocket = socket(AF_INET, SOCK_DGRAM)

for i in range(10):

    # 记录当前时间
    time1 = time.time()

    # 根据题目的要求来组装Ping消息
    outputdate = 'Ping' + str(i) + ' ' + str(time1)+' '

    # 设置超时时间为1秒
    clientsocket.settimeout(1)

    # 向服务器发送消息
    clientsocket.sendto(outputdate.encode(), (servername, serverport))

    try:
        # 等待服务器相应,计算往返时间
        message, serveradress = clientsocket.recvfrom(2048)

        # 计算数据往返时间
        timedff = time.time() - time1
        print(message.decode() + 'RTT:' + str(timedff))

    except:
        # 如果超时或者发生其他错误,则打印lost和当前Ping的编号
        print("lost" + str(i))

需要注意的点:

  • AF_INETSOCK_DGRAM是常量,它们分别表示IPv4地址族和UDP套接字类型。在这个例子中,我们使用的是IPv4和UDP。
  • sendto()是UDP套接字对象的一个方法,用于将消息通过UDP协议发送给指定的目标地址和端口。它接受两个参数:第一个参数是要发送的消息,必须是一个字节序列(即一个字符串需要通过encode()方法转换成字节序列),第二个参数是目标地址和端口的元组。在这个例子中,目标地址是servername,端口是serverport
  • decode()是Python的一个内置方法,用于将字节序列解码为字符串类型。在这个例子中,接收到的UDP数据报被解码为字符串类型,以便进行后续处理。

三、实验结果

首先,必须先运行UDPPingerServer.py程序,再运行UDPPingerclient.py程序。示意图如下:

四、附加实验

 目前,程序计算每个数据包的往返时间(RTT),并单独打印出来。请按照标准ping程序的模式修改。您需要在客户端每次ping后显示最小,最大和平均RTT。另外,还需计算丢包率(百分比)。

 只需要将UDPPingerclient.py的代码稍作修改即可,实验代码以及运行结果如下:

from socket import *
import time

# 定义ip地址和端口号
servername = '127.0.0.1'
serverport = 12000

# 创建一个UDP套接字
clientsocket = socket(AF_INET, SOCK_DGRAM)
print('正在Ping',servername,"数据:")

recenum=0         # 发送成功的个数
maxdifftime=-1    # 最大往返时间
mindifftime=2     # 最小往返时间
avgdifftime=0     # 平均往返时间

for i in range(10):

    # 记录当前时间
    time1 = time.time()

    # 根据题目的要求来组装Ping消息
    outputdate = 'Ping' + str(i) + ' ' + str(time1)+' '

    # 设置超时时间为1秒
    clientsocket.settimeout(1)

    # 向服务器发送消息
    clientsocket.sendto(outputdate.encode(), (servername, serverport))

    try:
        # 等待服务器相应,计算往返时间
        message, serveradress = clientsocket.recvfrom(2048)

        # 计算数据往返时间
        timedff = time.time() - time1
        print(message.decode()+' ',"来自",servername,"的回复:字节=",str(len(outputdate)),"RTT:",str(timedff))
        
        recenum+=1
        avgdifftime+=timedff
        if(timedff>maxdifftime):
            maxdifftime=timedff
        if(timedff<mindifftime):
            mindifftime=timedff

    except:
        # 如果超时或者发生其他错误,则打印lost和当前Ping的编号
        print("lost" + str(i))

print(servername,"的Ping统计信息:")
print("已发送:10","已接受:",str(recenum),"已丢失:",str(10-recenum),"丢包率:",str((10-recenum)/0.1)+"%")

if(recenum!=0):
    print("往返时间的估计时间(以秒为单位):")
    print("最大值:",maxdifftime,"最小值:",mindifftime,"平均值:",avgdifftime/recenum)

注:我们可以发现,最后生成的与往返时间相关的值都是0.0,初步判定原因是可能是因为服务器响应的时间太短了,导致计算得到的 timedff 值非常小,小到比你初始化的 maxdifftime 还要小,所以在计算过程中 maxdifftime 的值没有被更新。可以尝试延长超时时间或者加大数据包的大小,使服务器响应的时间变长。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值