如你所知,数据包格式套接字(Datagram Sockets)也叫“无连接的套接字”,在代码中使用 SOCK_DGRAM 表示。可以将 SOCK_DGRAM 比喻成高速移动的摩托车快递,它有以下特征:强调快速传输而非传输顺序;传输的数据可能丢失也可能损毁;限制每次传输的数据大小;数据的发送和接收是同步的。数据包套接字也使用 IP 协议作路由,但是它不使用 TCP 协议,而是使用 UDP 协议(User Datagram Protocol,用户数据报协议)。

实际应用中,QQ 视频聊天和语音聊天主要使用 SOCK_DGRAM 来传输数据,因为首先要保证通信的效率,尽量减小延迟,而数据的正确性是次要的,即使丢失很小的一部分数据,视频和音频也可以正常解析,最多出现噪点或杂音,不会对通信质量有实质的影响。(当然,SOCK_DGRAM 没有想象中的糟糕,不会频繁的丢失数据,数据错误只是小概率事件。)

我们将之前的程序改写一下,让服务端与客户端之间使用 UDP 协议进行通信。

服务端代码实现:

import time
from socket import *
import eventlet

eventlet.monkey_patch() #用于绿化一些python的模块
serverSocket=socket(AF_INET,SOCK_DGRAM)   #创建套接字对象
serverSocket.bind(("127.0.0.1",6666))      #绑定IP和端口,必须是元组形势

try:
    message,addr=serverSocket.recvfrom(1024)  #接受客户端连接,connectionSocket是客户端连接服务器的信号,addr是客户端地址
    print("收到"+addr[0]+":"+str(addr[1])+"的订单")
    time.sleep(10)  #让线程等待10秒
    serverSocket.sendto(bytes("您的订单已送达", encoding='utf-8'),addr)  # 向客户端发送消息
    for i in range(0,5):
        t=eventlet.Timeout(10,False)  #设置超时时间为10秒
        try:
            recv_data,addr=serverSocket.recvfrom(1024)
            print("收到消息,断开连接...")
            break
        except eventlet.timeout.Timeout as e:
            print("超时,重试中...")
            serverSocket.sendto(bytes("您的订单已送达", encoding='utf-8'),addr)  # 向客户端发送消息
        finally:
            t.cancel()        #终止进程
except IOError:
    serverSocket.close()  #关闭套接字对象
serverSocket.close()  #关闭套接字对象

客户端代码实现:

from socket import *

server_addr=("127.0.0.1",6666) #服务器的地址
clientSocket=socket(AF_INET,SOCK_DGRAM)     #创建套接字对象

try:
    print("等待外卖骑手送餐...")
    clientSocket.sendto(bytes("等待外卖骑手送餐...",encoding='utf-8'),server_addr)
    recv_data,addr=clientSocket.recvfrom(1024)        #接受服务器传来的消息
    print(str(recv_data,encoding='utf-8'))   #输出到控制台
    clientSocket.sendto(bytes("我已收到,谢谢",encoding='utf-8'),server_addr) #向服务端发送消息
except IOError:
    clientSocket.close()                     #关闭套接字对象

运行截图如下:

注意,此时使用 UDP 协议通信时,客户端与服务端之间没有建立连接,这是因为 UDP 协议本身就是无连接的。服务端不再监听客户端的连接状态,那么客户端就必须先发送消息告知对方,服务端才能知道客户下单了。

在实际生活中,UDP 协议被应用于视频、音频等多媒体通信。

更多推荐