Python中的端口协议之基于UDP协议的通信传输
程序员文章站
2022-05-21 20:21:26
UDP协议: 1、python中基于udp协议的客户端与服务端通信简单过程实现 2、udp协议的一些特点(与tcp协议的比较) 3、利用socketserver模块实现udp传输协议的并发通信 一、UDP协议:OSI七层协议中的传输协议的一种(另外一种tcp协议),他们都是一种端口协议 与TCP协议 ......
udp协议:
1、python中基于udp协议的客户端与服务端通信简单过程实现
2、udp协议的一些特点(与tcp协议的比较)
3、利用socketserver模块实现udp传输协议的并发通信
-------------------------------------------------------------------------------------------------------------------------------------
一、udp协议:osi七层协议中的传输协议的一种(另外一种tcp协议),他们都是一种端口协议
- 与tcp协议不同的是,udp协议在传输时候无需双方建立双向连接,只需要知道对方的ip和port(端口)就可以
而且udp协议传输具有不安全行,或者说是即时性,给对方发送信息时候,只管发,至于他收不收得到都不会去考虑,
不管是服务端还是客户端都一样。
- udp叫数据报协议,意味着发消息都带有数据报头,udp的server不需要进行监听也无需建立连接,在启动服务之后只能被动的等待客户端发消息过来,客户端发消息的时候,要带上服务端的地址,服务端在回消息的时候,也要带上客户端的地址
下面来简单实现基于udp协议的客户端、服务端通信
# 服务端: import socket # udp传输的服务端无需半连接池,因为通信无需建立双向连接通道,无需三次握手四次挥手,只要知道对方ip和port就行 server = socket.socket(socket.af_inet, socket.sock_dgram) server.bind(('127.0.0.1', 8080)) # 通信循环 while true: data, client_addr = server.recvfrom(1024) # 这里接收用recvfrom print('收到客户端发来的udp消息%s' % data.decode('utf-8')) server.sendto(data.upper(), client_addr) # 这里发送用sendto # 客户端: import socket # 无需connect服务端,因为发送时候跟上服务端ip和port就行 client = socket.socket(socket.af_inet, socket.sock_dgram) while true: msg = 'hello' client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080)) data, server_addr = client.recvfrom(1024) print(data.decode('utf-8'))
二、udp协议的一些特点
总结几个udp协议的特点:
- 客户端允许发空
- 不会粘包
- 服务端不存在的时候,客户端照发无误,不会报错(*-*)
- 可以实现简单的并发效果
# 验证udp是否有粘包问题: from socket import * server = socket(af_inet, sock_dgram) server.bind(('127.0.0.1', 8080)) while true: data1, addr = server.recvfrom(1024) data2, addr = server.recvfrom(1024) data3, addr = server.recvfrom(1024) data4, addr = server.recvfrom(1024) data5, addr = server.recvfrom(1024) print(data1) print(data2) print(data3) print(data4) print(data5) from socket import * client = socket(af_inet, sock_dgram) while true: client.sendto(b'hello1', ('127.0.0.1', 8080)) client.sendto(b'hello2', ('127.0.0.1', 8080)) client.sendto(b'hello3', ('127.0.0.1', 8080)) client.sendto(b'hello4', ('127.0.0.1', 8080)) client.sendto(b'hello5', ('127.0.0.1', 8080)) # 打印的每条数据都是独立的,没有2条数据在一起的情况 udp不存在粘包问题,是由于udp发送的时候,没有经过nagle算法的优化,不会将多个小包合并一次发送出去。另外,在udp协议的接收端,采用了链式结构来记录每一个到达的udp包,这样接收端应用程序一次recv只能从socket接收缓冲区中读出一个数据包。也就是说,发送端send了几次,接收端必须recv几次(无论recv时指定了多大的缓冲区)。
三、利用socketserver模块实现udp协议的并发通信
## 服务端: import socketserver from threading import currentthread # 这里导入当前线程方法,得到当前线程名称 class myudphandler(socketserver.baserequesthandler): def handle(self): # 这里和tcp利用socketserver模块并发的服务端不一样,tcp服务端是直接data = self.request.recv(1024) data, sock = self.request # 这里多了一个sock,这个sock用于发送,同时self对象本身可以得到client_address msg = '%s [%s]' % (currentthread().name, data.upper().decode('utf-8')) sock.sendto(msg.encode('utf-8'), self.client_address) if __name__ == '__main__': server = socketserver.threadingudpserver(('127.0.0.1', 8080), myudphandler) server.serve_forever() ## 客户端 from threading import thread,currentthread import time from socket import * def task(): client = socket(af_inet,sock_dgram) addr = ('127.0.0.1', 8080) n = 0 while n < 10: # 模拟让每个客户端与服务端通信循环10次。 msg = '%s [%s]' % (currentthread().name, n) client.sendto(msg.encode('utf-8'), addr) data, addr0 = client.recvfrom(1024) print(data.decode('utf-8')) n += 1 if __name__ == '__main__': for i in range(50): # 开启50个客户端线程去连接服务端,模拟并发 t = thread(target=task) t.start()
上一篇: 8年开发经验程序员告诉你,零基础如何快速学习好python?
下一篇: 中国站长第一人:李兴平