Python套接字对象是否安全?

时间:2017-03-17 11:19:16

标签: python multithreading sockets udp

我计划设计一个如下工作的UDP服务器:我将与防火墙后面的客户端进行通信,并且需要能够随时发送数据。因此,客户端将首先启动与我的连接,并通过定期发送保持活动数据包来定期保持连接活动。当我收到一个,我需要承认它。同时,如果我要发送任何数据,我需要立即发送。我把以下测试代码放在一起:

import threading
import queue
import socket
import time

class SharedAddress():
    def __init__(self):
        self.lock = threading.Lock()
        self.addr = ()

    def set_addr(self, addr):
        self.lock.acquire()
        self.addr = addr
        self.lock.release()

    def get_addr(self):
        self.lock.acquire()
        addr = self.addr
        self.lock.release()
        return addr

class Reader(threading.Thread):
    def __init__(self, socket, shared_address):
        super().__init__(name='Reader Thread')
        self.socket = socket
        self.shared_address = shared_address

    def run(self):
        while True:
            # Wait for data from the client
            data, addr = self.socket.recvfrom(4096)
            #print("Received data from {}".format(addr))
            # Echo it back
            self.socket.sendto(data, addr)
            self.shared_address.set_addr(addr)

class Writer(threading.Thread):
    def __init__(self, socket, shared_address):
        super().__init__(name='Writer Thread')
        self.socket = socket
        self.tx_queue = queue.Queue()
        self.shared_address = shared_address

    def run(self):
        while True:
            # Wait for data to be received
            data = self.tx_queue.get()
            # Send it to the client
            addr = self.shared_address.get_addr()
            if addr:
                self.socket.sendto(data, addr)



### Main loop
# Create the socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('', 2000))

sa = SharedAddress()

r = Reader(s, sa)
w = Writer(s, sa)

r.start()
w.start()

while True:
    w.tx_queue.put(b'>>Hi this is a message<<\n')
    time.sleep(0.1)

r.join()
w.join()

print("Program ended")

虽然代码似乎有用,但我担心的是我在两个不同的线程中使用相同的套接字对象而没有任何锁定。然后我修改了Writer类来创建自己的套接字对象:

class Writer(threading.Thread):
    def __init__(self, shared_address):
        super().__init__(name='Writer Thread')
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
        self.tx_queue = queue.Queue()
        self.shared_address = shared_address

这似乎也很好用。我的问题如下:

  • 套接字对象线程是否安全?
  • 如果您在Python中创建多个UDP套接字对象并使用它们将数据发送到同一地址,那么它们实际上最终会引用相同的底层连接对象吗?
  • 如果我在其中一个套接字对象上调用close命令会怎样?据推测,它将关闭底层的OS套接字并阻止其他套接字对象接收和传输。

1 个答案:

答案 0 :(得分:-1)

如果您愿意,可以使用zmq

PyZMQ