当使用阻塞式UDP socket时无法执行多任务处理,也无法与用户交互,甚至不能响应ctrl+c中断。为了解决这些问题所以要用非阻塞式udp通信。
1,多线程法
import socket
import signal
import threading
import time
def handler(signal_received, frame):
# Handle any cleanup here
if signal_received == signal.SIGINT:
print('SIGINT or CTRL-C detected. Exiting gracefully')
exit(0)
def task(host, port):
print("udp server is listen on " + str(host) + ':' + str(port))
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print("from %s received message: %s" % (addr, data))
if __name__ == '__main__':
signal.signal(signal.SIGINT, handler=handler) # ctlr + c
UDP_IP = "0.0.0.0"
UDP_PORT = 5005
t = threading.Thread(target=task, args=(UDP_IP, UDP_PORT))
t.daemon = True
t.start()
while True:
time.sleep(100)
2, 协程法
官方文档说不要在应用中使用asyncio,而是应该在框架中用
import asyncio
class EchoServerProtocol:
def __init__(self, message, on_con_lost):
self.message = message
self.on_con_lost = on_con_lost
self.transport = None
def connection_made(self, transport):
self.transport = transport
def datagram_received(self, data, addr):
print('Received %r from %s' % (data.decode(), addr))
self.transport.sendto(data, addr)
def error_received(self, exc):
print('Error received:', exc)
def connection_lost(self, exc):
print("Connection closed")
self.on_con_lost.set_result(True)
async def main():
print("Starting UDP server")
# Get a reference to the event loop as we plan to use
# low-level APIs.
loop = asyncio.get_running_loop()
on_con_lost = loop.create_future()
message = 'Hello World!'
# One protocol instance will be created to serve all
# client requests.
transport, protocol = await loop.create_datagram_endpoint(
lambda: EchoServerProtocol(message, on_con_lost=on_con_lost),
local_addr=('127.0.0.1', 9999),
remote_addr=('127.0.0.1', 5005))
try:
while True:
await asyncio.sleep(10) # Serve for 1 hour.
finally:
transport.close()
try:
asyncio.run(main())
except KeyboardInterrupt:
print('Got signal: SIGINT, shutting down.')
exit(0)