2016-12-07 84 views
0

我只有一个连接到java服务器的套接字对象的python脚本。多线程中的python套接字recv

我开始了一个线程,每5秒向服务器发送心跳消息。

而另一个接收来自服务器的消息的线程。

顺便说一下,所有send/recv数据都是protobuffer格式。

# 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(...) 

这里是我试过的要求做:

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 

我遇到的问题是我在请求方法接收的呼叫发送方法后的数据似乎是由被干扰心跳在线程中的数据。

如果我注释掉心跳线程和接收线程,那么请求方法就会工作得很好。来自服务器的数据可以解码而不会出错,并且可以成功地将其发送回浏览器。

我的解决方案现在可能是错误的,我真的不知道如何获得这项工作。

任何建议将赞赏,感谢:)

回答

1

socket在Python对象不是线程安全的,你需要一些同步原语的帮助下访问共享资源(在这种情况下对象),如Python 2中的threading.Lock。在这里检查是否有类似问题:Python: Socket and threads?