使用 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
为每个连接的客户端创建一个新套接字。
我正在尝试实现 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
为每个连接的客户端创建一个新套接字。