这部分回顾Socket Programming Assignment 2: UDPpinger。

参考资料:

简介

此次作业的目的是熟悉UDP套接字编程,实现Pinger程序,主要任务如下:

  • 实现基本的Pinger客户端
  • 实现增强的Pinger客户端
  • 实现Heartbeat客户端与服务器

文件路径结构如下:

Socket2_UDPpinger/
|-- UDPHeartbeatClient.py
|-- UDPHeartbeatServer.py
|-- UDPPingerServer.py
|-- client.py
`-- client_enhance.py

文件解释如下:

  • UDPPingerServer.py:Pinger服务器,无需实现;
  • client.py:基本的Pinger客户端;
  • client_enhance.py:增强的Pinger客户端;
  • UDPHeartbeatClient.py, UDPHeartbeatServer.py:Heartbeat客户端与服务器

基本的Pinger客户端

客户端client.py的参数为模拟次数,代码如下:

from socket import *
import time
import sys

def ping(message, clientSocket, serverName, serverPort):
    start = time.time()
    try:
        clientSocket.sendto(message.encode(), (serverName, serverPort))
        rawdata, serverAddress = clientSocket.recvfrom(2048)
        end = time.time()
        data = rawdata.decode()
        if len(data) == 0:
            return -1
        else:
            return end - start
    except:
        return -1

def main():
    n = int(sys.argv[1])
    serverName = "localhost"
    serverPort = 12000
    # setdefaulttimeout(1)
    clientSocket = socket(AF_INET, SOCK_DGRAM)
    # 设置延迟上限
    clientSocket.settimeout(1)
    message = "test"
    for i in range(1, n + 1):
        response_time = ping(message, clientSocket, serverName, serverPort)
        if (response_time < 0):
            print(f"Pint {i} Request timed out")
        else:
            print(f"Ping {i} {response_time}")
    clientSocket.close()

if __name__ == '__main__':
    main()

启动服务器以及客户端:

python UDPPingerServer.py

python client.py 10

实验结果:

Ping 1 0.010045766830444336
Ping 2 0.0019996166229248047
Ping 3 0.0015840530395507812
Ping 4 0.002002239227294922
Ping 5 0.0010035037994384766
Ping 6 0.0019953250885009766
Pint 7 Request timed out
Ping 8 0.0010006427764892578
Pint 9 Request timed out
Ping 10 0.0010013580322265625

增强的Pinger客户端

client_enhance.py增加一些统计功能,代码如下:

from socket import *
import time
import sys

def ping(message, clientSocket, serverName, serverPort):
    start = time.time()
    try:
        clientSocket.sendto(message.encode(), (serverName, serverPort))
        rawdata, serverAddress = clientSocket.recvfrom(2048)
        end = time.time()
        data = rawdata.decode()
        if len(data) == 0:
            return -1
        else:
            return end - start
    except:
        return -1

def main():
    n = int(sys.argv[1])
    serverName = "localhost"
    serverPort = 12000
    # setdefaulttimeout(1)
    clientSocket = socket(AF_INET, SOCK_DGRAM)
    clientSocket.settimeout(1)
    message = "test"
    # stat data
    min_time = 100
    max_time = 0
    all_rtt = 0
    sucess_time = 0
    for i in range(1, n + 1):
        response_time = ping(message, clientSocket, serverName, serverPort)
        if (response_time < 0):
            print(f"Pint {i} Request timed out")
        else:
            print(f"Ping {i} {response_time}")
            min_time = min(response_time, min_time)
            max_time = max(response_time, max_time)
            all_rtt += response_time
            sucess_time += 1
    clientSocket.close()

    print(f"Min rtt is {min_time}.")
    print(f"Max rtt is {max_time}.")
    print(f"Mean rtt is {all_rtt / sucess_time}.")
    print(f"Loss rate is {1 - sucess_time / n}")

if __name__ == '__main__':
    main()

启动服务器以及客户端:

python UDPPingerServer.py

python client_enhance.py 10

实验结果:

Ping 1 0.0046536922454833984
Ping 2 0.004335165023803711
Ping 3 0.001005411148071289
Pint 4 Request timed out
Ping 5 0.0009920597076416016
Ping 6 0.0010023117065429688
Ping 7 0.0009989738464355469
Pint 8 Request timed out
Ping 9 0.0020017623901367188
Ping 10 0.0009965896606445312
Min rtt is 0.0009920597076416016.
Max rtt is 0.0046536922454833984.
Mean rtt is 0.0019982457160949707.
Loss rate is 0.19999999999999996

Heartbeat客户端与服务器

服务器

使用try, except来判断客户端是否运行,UDPHeartbeatServer.py代码如下:

# UDPHeartbeatServer.py 
# We will need the following module to generate randomized lost packets import random 
from socket import *
import time

# Create a UDP socket  
# Notice the use of SOCK_DGRAM for UDP packets 
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.settimeout(20)
# Assign IP address and port number to socket 
serverSocket.bind(('', 12000)) 

while True:     
	# Receive the client packet along with the address it is coming from  
	try:
		message, address = serverSocket.recvfrom(1024)
	except:
		print("Client is stop!")
		break
	end_time = time.time()
	if (len(message) == 0):
		print("Message loss!")
		continue
	proc_message = message.decode().split()
	number = proc_message[0]
	start_time = float(proc_message[1])
	diff_time = end_time - start_time
	print(f"Number is {number}, time difference is {diff_time}")

serverSocket.close()

客户端

UDPHeartbeatClient.py的参数为模拟次数,代码如下:

from socket import *
import time
import sys
import random
import time

def main():
    n = int(sys.argv[1])
    serverName = "localhost"
    serverPort = 12000
    # setdefaulttimeout(1)
    clientSocket = socket(AF_INET, SOCK_DGRAM)
    for i in range(n):
        message = f"{random.random()} {time.time()}"
        clientSocket.sendto(message.encode(), (serverName, serverPort))

if __name__ == '__main__':
    main()

实验

启动服务器以及客户端:

python UDPHeartbeatServer.py

python UDPHeartbeatClient.py 10

实验结果如下(服务器):

Number is 0.9437354115592858, time difference is 0.009946107864379883
Number is 0.9912950642511882, time difference is 0.004694700241088867
Number is 0.9050499296678337, time difference is 0.001194000244140625
Number is 0.037575470500414654, time difference is 0.00034427642822265625
Number is 0.6443998739965965, time difference is 0.0010006427764892578
Number is 0.7365591696001208, time difference is 0.0010039806365966797
Number is 0.671174745360197, time difference is 0.0009975433349609375
Number is 0.3638988163490168, time difference is 0.0
Number is 0.947734778694654, time difference is 0.000997781753540039
Number is 0.7965422860215524, time difference is 0.001001596450805664
Client is stop!