前言
工作中遇到各种各样的网络通信。有MQTT和CoAP这样的物联网应用层协议,也有各种自定义的TCP或UDP协议。使用各种不同的计算机语言和框架开发网络通信,例如Java的Netty框架,C语言原始socket,Python Socket。各有各的使用场景,难易程度相差巨大。Netty上手困难,C语言编写复杂,Python Socket上手容易。
长久以来,UDP通信一直被误解为一种不可靠的通信手段,但是UDP简单使用,特别适合物联网终端。UDP没有三次握手和四次挥手,换个角度来说节约了网络流量,降低了设备的功耗。
示例简述
- 本例通过UDP Socket实现客户端和服务器
- 客户端主动发送一组数据至服务器,客户端收到服务器的响应后打印至控制台
- 服务器收到客户端的请求后,把请求内容原样返回值客户端
- 本例模拟,物联网终端设备与服务器通信,推荐使用bytes类型而不是string
- 开发环境 Windows PyCharm社区版 Python3.7
UDP客户端
udp-client.py
import socket
import binascii
# 指定服务器地址和端口号,务必根据实际情况修改
HOST = '127.0.0.1'
PORT = 50018
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定本机50019端口
s.bind(('', 50019))
request = bytearray([0x31, 0x32, 0x33, 0x34])
s.sendto(request, (HOST, PORT))
response, server_address = s.recvfrom(1024)
print('received', binascii.hexlify(response), "from", server_address)
代码说明
- UDP客户端无需使用
connect
,但是UDP客户端也可以使用bind
指定本机端口号 - 设置套接字类型为
socket.SOCK_DGRAM
,而TCP套接字类型为socket.SOCK_STREAM
-
s.bind(('', 50019))
绑定本地端口号为50019,绑定本地端口号后服务器将收到50019端口的请求,若不指定本机将会分配一个随机端口 - UDP套接字发送为
sendto
,接收为recvfrom
UDP服务器
udp-server.py
import socket
import binascii
HOST = ''
PORT = 50018
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((HOST, PORT))
while True:
request, client_address = s.recvfrom(1024)
print('connected by', client_address,
'received ', binascii.hexlify(request))
if request:
s.sendto(request, client_address)
代码说明
- HOST = '' "和s.bind((HOST, PORT))绑定本地主机所有IP地址
- HOST = '' "也可以写成
0.0.0.0
,同样为绑定本机所有IP地址 - 通过binascii.hexlify打印HEXSTRING
运行与测试
先启动UDP服务器,再启动UDP客户端。
服务器控制台可能输出
connected by ('127.0.0.1', 50019) received b'31323334'
connected by ('192.168.3.18', 5009) received b'31323334'
客户端控制台可能输出
received b'31323334' from ('127.0.0.1', 50018)
总结
- 相比于Java Netty框架编写UDP 客户端和服务器,Python实现一组UDP客户端和服务器真的是太容易了。
相关资料
- 本例代码仓库【 python-socket-demo】
- 物联网图书推荐 CoAP基础 徐凯《IoT开发实战: CoAP卷》 2017 机械工业出版社【 京东链接】
- 物联网图书推荐 CoAPs进阶 徐凯 崔红鹏《密码技术与物联网安全:mbedtls开发实战》2019 机械工业出版社 【京东链接】