使用 Python 线程化 udp 数据

Threading udp datas with Python

我正在尝试实现 UDP 套接字的线程。

我希望能够在一个线程中等待客户向我发送一些数据,并在另一个线程中等待第一个数据。

import threading
import socket

class Broker():

    def __init__(self):
          self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
          self.sock.bind(('127.0.0.1', 4242))
          self.clients_list = []

    def talkToClient(self, ip):
            self.sock.sendto("ok", ip)

    def listen_clients(self):
            while True:
                msg, client = self.sock.recvfrom(1024)
                t = threading.Thread(None, self.talkToClient, None, (client,), None)

b = Broker()
b.listen_clients()

和我的客户

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

sock.sendto("connection", ('127.0.0.1', 4242))

while True:
    msg, b = sock.recvfrom(1024)
    print msg

问题是我的客户从未收到 "ok"

您的主要问题是您没有启动您创建的线程。

t.start()

应该做的。请确保您也使用四个空格进行缩进。

我自己并没有首先看到错误,但是一旦我添加了一些日志记录语句,它就非常明显了。代码最终看起来像这样:

import threading
import socket
import logging

class Broker():

    def __init__(self):
        logging.info('Initializing Broker')
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(('127.0.0.1', 4242))
        self.clients_list = []

    def talkToClient(self, ip):
        logging.info("Sending 'ok' to %s", ip)
        self.sock.sendto("ok", ip)

    def listen_clients(self):
        while True:
            msg, client = self.sock.recvfrom(1024)
            logging.info('Received data from client %s: %s', client, msg)
            t = threading.Thread(target=self.talkToClient, args=(client,))
            t.start()

if __name__ == '__main__':
    # Make sure all log messages show up
    logging.getLogger().setLevel(logging.DEBUG)

    b = Broker()
    b.listen_clients()

不过,由于您的线程解决方案,恐怕您会 运行 遇到其他问题。默认情况下,大多数 python 模块不是线程安全的,不幸的是这是 true for the socket module as well。我很确定你的套接字的内部状态最终会被破坏,因为你在一个线程中读取并在另一个线程中写入,或者可能在许多其他线程中因为你为每个客户端生成一个新进程。

如果您查看 multi-threaded socket code examples in Python, a socket is usually owned and used by only one thread. The key is to not reuse the listening socket for clients, but to use socket.accept 为每个连接的客户端创建一个新套接字。