我正在使用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))
答案 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
使用以下代码,以避免必须显式获取和释放锁。
我希望它有所帮助