在多个线程中侦听套接字输入

时间:2017-06-07 06:22:50

标签: python multithreading sockets

我正在使用python套接字。

这是问题所在。我有两个帖子:

  • 一个线程侦听来自远程的套接字输入并回复它
  • 一个线程轮询文件,如果文件中存在某些内容,则发送 插座并期待响应。

现在问题出在第二个线程的情况下,当我发送东西时,响应没有来到这个线程。而是涉及(1)点中提到的线程。

这是主题(1)

def client_handler(client):
    global client_name_to_sock_mapping
    client.send(first_response + server_name[:-1] + ", Press ^C to exit")
    user_name = None
    while True:
        request = client.recv(RECV_BUFFER_LIMIT)
        if not user_name:
            user_name = process_input(client, request.decode('utf-8'))
            user_name = user_name.rstrip()
            if user_name not in client_name_to_sock_mapping.keys():
                client_name_to_sock_mapping[user_name] = client
            else:
                msg = "Username not available".encode('ascii')
                client.send(msg)
        else:
            process_input(client, request.decode('utf-8'), user_name)

def client_handler(client): global client_name_to_sock_mapping client.send(first_response + server_name[:-1] + ", Press ^C to exit") user_name = None while True: request = client.recv(RECV_BUFFER_LIMIT) if not user_name: user_name = process_input(client, request.decode('utf-8')) user_name = user_name.rstrip() if user_name not in client_name_to_sock_mapping.keys(): client_name_to_sock_mapping[user_name] = client else: msg = "Username not available".encode('ascii') client.send(msg) else: process_input(client, request.decode('utf-8'), user_name)

这是从线程(2)运行的

def send_compute_to_client():
    time.sleep(20)
    print("Sleep over")
    for _, client_sock in client_name_to_sock_mapping.iteritems():
        print("client = {}".format(client_sock))
        client_sock.sendall("COMPUTE 1,2,3")
        print("send completed = {}".format(client_sock))
        data = client_sock.recv(1024)
        print("Computed results from client {}".format(data))
有人可以解释一下这种行为吗?

1 个答案:

答案 0 :(得分:1)

我过去遇到过类似的问题。当在一个线程中,您在通过同一套接字发送的另一个线程中启动阻塞操作时,会发生这种情况。

如果我理解得很清楚,您总是希望收到先前发送数据的响应。因此,为了解决这个问题,我会使用锁来强制执行该行为,因此只需创建一个类:

from threading import Lock

class ConnectionSession:
  def __init__(self, address, conn):
    self.ip = address[0]  # Optional info
    self.port = address[1] # Optional info
    self.conn = conn
    self.lock = Lock()

这里介绍了如何在创建侦听套接字时正确创建ConnectionSession对象:

address = ('127.0.0.1', 46140)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(address)
conn, addr = s.accept()
session = ConnectionSession(addr, conn)

这是在创建“发送”连接时:

address = ('127.0.0.1', 46140)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(address)
session = ConnectionSession(address, s)

请记住,创建的会话实例是需要在线程之间共享的实例。

之后,要通过共享套接字发送信息,您可以在每个线程中执行以下操作:

# Previous code
try:
    session.lock.acquire()
    session.conn.sendall("Hi there buddy!")
    # Do something if needed
    message = session.conn.recv(1024)
except Exception as e:
    print "Exception e=%s should be handled properly" % e
finally:
    if session.lock.locked():
        session.lock.release()
# Other code

请注意,finally块很重要,因为它会释放锁定的连接,无论操作是否成功。

您还可以将以前的代码包装在一个类中,例如:SocketManager使用以下代码,以避免必须显式获取和释放锁。

我希望它有所帮助