Socket編程:UDP Ping
使用python采用UDP協議編寫一個ping程序,發送一個簡單的ping報文給服務器,並確定從客戶發送ping報文服務器到接受到pong報文為止的時延,稱為往返時延(RTT) 。
因為UDP是一個不可靠的協議,客戶發送的分組可能會丟失,為此,客戶不能無限期地等待服務器的響應,等待時間至多為1s,否則,打印一條錯誤信息。
UDP_Pinger_Sever.py
import random
from socket import *
#AF_INET指定使用IPv4協議,如果要用更先進的IPv6,就指定為AF_INET6
#SOCK_DGRAM指定了這個Socket的類型是UDP
serverSocket = socket(AF_INET, SOCK_DGRAM)
#用0.0.0.0綁定到所有的網絡地址,還可以用127.0.0.1綁定到本機地址
serverSocket.bind(('127.0.0.1',12000))
while True:
#產生一個0到10之間的隨機數
rand = random.randint(0, 10)
#從套接口上讀取數據,參數為緩沖區大小
message, address = serverSocket.recvfrom(1024)
#通過打印我們可以看到UDP客戶端socket的端口是不確定,系統隨機分配的
print("收到來自 %s 的報文: (%s)" % (address,message))
# 把接收到的信息全部轉為大寫
print("隨機數是: %d" % rand)
message = message.upper()
#如果隨機數小於4,服務端無應答,客戶端就會超時
if rand < 4:
continue
serverSocket.sendto(message, address)
UDP_Pinger_Client.py
import time
from socket import *
serverName = '127.0.0.1' # 主機
serverPort = 12000
# 創建Socket時,AF_INET指定使用IPv4協議,如果要用更先進的IPv6,就指定為AF_INET6
# SOCK_DGRAM指定了這個Socket的類型是UDP
# SOCK_STREAM指定使用面向流的TCP協議
clientSocket = socket(AF_INET, SOCK_DGRAM)
clientSocket.settimeout(1) # 設置超時時間為1s
for i in range(0, 10):
oldTime = time.time()
sendTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(oldTime))
# encode()把str轉成bytes,傳輸格式要求
message = ('package %d,client_local_time:%s' % (i + 1, sendTime)).encode()
try:
# 發送數據
clientSocket.sendto(message, (serverName, serverPort))
# 1024指定要接收的最大數據量為1kb = 1024 bytes
# recvfrom是一個系統調用,由用戶態轉向系統態,從套接口上接收數據,並捕獲數據發送源的地址。
# 如果數據報大於緩沖區,那么緩沖區中只有數據報的前面部分,其他的數據都丟失了,並且recvfrom()函數返回WSAEMSGSIZE錯誤
# 如果沒有數據待讀,那么除非是非阻塞模式,不然的話套接口將一直等待數據的到來,果沒有在Timeout = 1s內接收到數據,此時將返回SOCKET_ERROR錯誤,錯誤代碼是WSAEWOULDBLOCK。用select()或WSAAsynSelect()可以獲知何時數據到達
# UDP的 recvfrom() 和 TCP 的recv()不一樣,具體可以看 TCP Ping項目
modifiedMessage, serverAddress = clientSocket.recvfrom(1024)
# 計算往返時間
rtt = time.time() - oldTime
# decode 把bytes轉成str
modifiedMessage = modifiedMessage.decode("utf-8")
print('報文 %d 收到來自 %s 的應答: %s,往返時延(RTT) = %fs' % (i+1, serverName,modifiedMessage, rtt))
except Exception as e:
print('報文 %d: 的請求超時' % (i+1)) # 處理異常
運行

