前言
工作中遇到各种各样的网络通信。有MQTT和CoAP这样的物联网应用层协议,也有各种自定义的TCP或UDP协议。使用各种不同的计算机语言和框架开发网络通信,例如Java的Netty框架,C语言原始socket,Python Socket。各有各的使用场景,难易程度相差巨大。Netty上手困难,C语言编写复杂,Python Socket上手容易。
长久以来,UDP通信一直被误解为一种不可靠的通信手段,但是UDP简单使用,特别适合物联网终端。UDP没有三次握手和四次挥手,换个角度来说节约了网络流量,降低了设备的功耗。UDP协议也是物联网应用层协议CoAP、LwM2M的传输层协议,也有消息说HTTP 3.0协议将使用UDP作为传输层协议
示例简述
- 本例通过
select
实现一个UDP Server,一般来说select相比其他recv和send等常用函数难用不少,网上也很难找到合适的示例,特别是UDP Select示例。 - 开发环境 Windows PyCharm社区版 Python3.7
服务器示例
udp-server-select.py
import select
import socket
import binascii
HOST = ''
PORT = 50018
server_fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_fd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_fd.bind((HOST, PORT))
print('starting up on %s port %s' % (HOST, PORT))
# 把服务器套接字加入到输入列表中
inputs = [server_fd]
client_address = None
conn = None
while True:
# readable, writable, exceptional = select.select(inputs, [], [], 1.0)
readable = select.select(inputs, [], [], 1.0)[0]
for s in readable:
data, client_address = s.recvfrom(1024)
if data:
# 收到客户端数据
print('received "%s" from %s' % (binascii.hexlify(data), client_address))
s.sendto(data, client_address)
代码说明
-
inputs = [server_fd]
创建套接字后把服务器套接字加入到输入列表中 - select函数有4个输入参数,分别为输入列表、输出列表、错误列表和超时时间,输出参数为一个Python元组类型,分别为可读列表、可写列表和错误列表。select函数原型如下:
select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)
- 如果仅需要查询可读列表,可以简写为
select.select(inputs, [], [], 1.0)[0]
,也就是选择select返回元组类型的第0个元素。
客户端示例
运行与测试
先启动UDP服务器,再启动UDP客户端。
服务器控制台可能输出
connected by ('127.0.0.1', 50019) received b'31323334'
connected by ('192.168.3.18', 50019) received b'31323334'
客户端控制台可能输出
received b'31323334' from ('127.0.0.1', 50018)
相关资料
- 本例代码仓库【 python-socket-demo】
- 物联网图书推荐 CoAP基础 徐凯《IoT开发实战: CoAP卷》 2017 机械工业出版社【 京东链接】
- 物联网图书推荐 CoAPs进阶 徐凯 崔红鹏《密码技术与物联网安全:mbedtls开发实战》2019 机械工业出版社 【京东链接】