附上一段自己写的代码:【物联网项目分支】
以下代码打算完成的是,使用线程启动多线程监听UDP端口服务。
具体是这样的数据量大的时候,本想使用多线程监听同一个端口,然后将线程翻到列表中,这样就不用频繁创建销毁线程,使得系统资源消耗大。使用线程监听后将数据放到队列中,在另外启动线程进行数据的处理,并且使用锁将队列锁住进行处理。
使用Queue队列(FIFO)进行存储数据后线程将监听的数据进行存入队列。数据处理线程则进行数据处理。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import socket
import json
import traceback

import Queue
import threading
import time
#设置标志位
Sign = 1
# 创建一个无限大小的队列
workQueue = Queue.Queue()
#queueLock = threading.Lock()
threads = []
#运行监听线程
class monitorUdpThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.MonitorUdp=UDPsever()
        print('Start listening on one-------')
    def run(self):
        print('Getting Data Method Start')
        self.MonitorUdp.getData()
        time.sleep(0.5)
        print('End of data acquisition method')
        
#运行线程 创建监听线程
class createThread(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
            threads=[]
        def run(self):
                for tName in range(5):
                        thread = monitorUdpThread()
                        thread.start()
                        threads.append(thread)
                        Sign = 0

class UDPsever(object):
    def __init__(self):
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.PORT = 9090
        self.bufsiz = 2048
        # [2][0] 2保持不变,如果删除[0]会输出本机所有网卡获取的IP地址,[0]为0时获取的是本地连接的IP地址
        self.IP=socket.gethostbyname_ex(socket.gethostname())[2][0]
        address = (self.IP, self.PORT)
        # print(address)
        # self.server_socket.listen(10)
        #将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。
        try:
                self.server_socket.bind(address)
        except OSError:
                print('通常每个套接字地址(协议/网络地址/端口)只允许使用一次')

    def getData(self):
        """
        客户端接收服务器的消息
        :return:
        """
        try:
            # 接受套接字的数据。数据以字符串形式返回,返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
            receive_data_bytes, client_address = self.server_socket.recvfrom(self.bufsiz)
            print(receive_data)
            workQueue.put(receive_data)
            # print(type(receive_data))
        except json.decoder.JSONDecodeError:
            print('json.decoder.JSONDecodeError')
        except UnicodeDecodeError:
            print('UnicodeDecodeError')
            # return client_address[0], client_address[1],receive_data
            
#处理数据的类
class HandleUdpThread(threading.Thread):
    def __init__(self):
            threading.Thread.__init__(self)
            self.queueLock = threading.Lock()
    def run(self):
        self.queueLock.acquire()
        if not workQueue.empty():
            data = q.get()
            self.queueLock.release()
            print (data)
        else:
            self.queueLock.release()



class startALLThread(object):
        def __init__(self):
                self.createthread = createThread()
                self.biaozhi = 1
        def start(self):
        #启动创建监听线程
                self.createthread.start()
                for tName2 in range(5):
                        Thread1 = HandleUdpThread()
                        Thread1.start()
                        threads.append(Thread1)
                        print('End of creation')
        def stop(self):
                # 等待所有线程完成
                while self.biaozhi:
                        # Queue.empty() 如果队列为空,返回True,反之False
                        if not workQueue.empty():
                                # 等待线程运行结束,并且标志位置0
                                for t in threads:
                                        t.join()
                                self.biaozhi = 0
startA = startALLThread()
startA.start()
startA.stop()

但是,程序运行后出现如下错误。

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File "C:\Users\Administrator\Desktop\ThreadUDP.py", line 35, in run
    thread = monitorUdpThread()
  File "C:\Users\Administrator\Desktop\ThreadUDP.py", line 20, in __init__
    self.MonitorUdp=UDPsever()
  File "C:\Users\Administrator\Desktop\ThreadUDP.py", line 51, in __init__
    self.server_socket.bind(address)
OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。

如果忽略此错误,则在之后创建的线程则会提示:

Exception in thread Thread-5:
Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File "C:\Users\Administrator\Desktop\ThreadUDP.py", line 24, in run
    self.MonitorUdp.getData()
  File "C:\Users\Administrator\Desktop\ThreadUDP.py", line 63, in getData
    receive_data_bytes, client_address = self.server_socket.recvfrom(self.bufsiz)
OSError: [WinError 10022] 提供了一个无效的参数。

原因是前面套接字出现错误后我将错误忽略了,导致self.server_socket.bind(address)未能成功绑定地址和端口号。而 UDP数据报通信发生在源端口和目标端口之间。可以bind通过调用其中一个send / recv方法为端口分配呼叫或让网络堆栈为我们选择一个。如果调用sendto(并且没有绑定端口),则堆栈将在动态端口范围中分配一个数字。如果你调用recvfrom,堆栈通常会分配端口0 但是没有端口0 接下来发生的是平台相关的。Windows将尝试将您绑定为混杂的侦听器。但这是一个特权调用,你可能会得到一个无效的参数错误。但如果是管理员,它可能会奏效。