我有一个python脚本,只有一个socket对象连接到java服务器。
我启动了一个线程,用于每5秒向服务器发送一次心跳消息。
和另一个线程,用于接收来自服务器的消息。
顺便说一句,所有的数据发送/接收都是协议缓冲区格式。
# socket_client.py
def recv_handler():
global client_socket
while True:
try:
# read 4 bytes first
pack_len = client_socket.recv(4)
pack_len = struct.unpack('!i', pack_len)[0]
# read the rest
recv_data = client_socket.recv(pack_len)
# decode
decompressed_data = data_util.decompressMessage(recv_data)
sc_pb_message = data_util.decodePBMessage(decompressed_data)
sc_head = data_util.parseHead(sc_pb_message)
except:
print 'error'
def heart_handler():
global client_socket
while True:
if client_socket:
message = data_util.makeMessage('MSG_HEART_BEAT')
compressed_data = data_util.compressMessage(message)
send_data = data_util.makeSendData(compressed_data)
try:
client_socket.send(send_data)
except:
print 'except'
pass
time.sleep(5)
def connect(address, port):
global client_socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((address, port))
# thread sending heart beat message
th = threading.Thread(target = heart_handler)
th.start()
# thread recving message
tr = threading.Thread(target = recv_handler)
tr.start()上面的代码运行得很好。该脚本将每5秒发送一条心跳消息,并从服务器接收该消息,该消息可以成功解码。
现在来了触发器部分,我不知道如何实现。
我的python脚本需要同时接收来自浏览器的输入,所以我启动了一个BaseHTTPServer来处理来自浏览器的POST请求。
当请求到来时,我希望调用client_socket.send方法向服务器发送特定的消息,当然,我需要将数据从服务器返回给浏览器。
# http_server.py
def do_POST(self):
# ...
result = socket_client.request(message)
self.send_response(200)
self.end_headers()
self.wfile.write(...)下面是我在request中尝试做的事情:
def request(message):
global client_socket
client_socket.send(message)
pack_len = client_socket.recv(4)
pack_len = struct.unpack('!i', pack_len)[0]
recv_data = client_socket.recv(pack_len)
return recv_data我遇到的问题是,在调用send方法之后,我在request方法中收到的数据似乎被线程中的心跳数据干扰。
如果我注释掉了心跳线程和接收线程,那么request方法就可以正常工作了。来自服务器的数据可以无差错地解码,并且可以成功地发送回浏览器。
我现在的解决方案可能是错误的,我真的不知道如何让这个工作。
任何建议都将不胜感激,谢谢:)
发布于 2016-12-07 15:26:37
Python2中的socket对象不是线程安全的,您需要借助一些同步原语(如Python2中的threading.Lock )访问共享资源(在本例中为client_socket对象)。
https://stackoverflow.com/questions/41011063
复制相似问题