2016-12-07 2 views
0

Ich habe Python-Skript mit nur einem Socket-Objekt, das mit einem Java-Server verbunden ist.Python Socket recv in Multithread

Ich begann einen Thread zum Senden von Herzschlag Nachricht an den Server alle 5 Sekunden.

Und ein weiterer Thread zum Empfangen von Nachrichten vom Server.

BTW, alle Daten senden/recv ist im Protobuffer-Format.

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

Der obige Code funktioniert gut. Das Skript sendet eine Herzschlagnachricht alle 5 Sekunden und empfängt die Nachricht vom Server und die Nachricht kann erfolgreich dekodiert werden.

Und hier kommt der Auslöser Teil als ich nicht wissen, wie zu implementieren.

Mein Python-Skript muss zur gleichen Zeit Eingaben vom Browser erhalten, also habe ich einen BaseHTTPServer gestartet, um die POST-Anfrage vom Browser zu bearbeiten.

Wenn eine Anfrage kommen, möchte ich die Methode client_socket.send aufrufen, um eine bestimmte Nachricht an den Server zu senden, und natürlich muss ich die Daten vom Server zurück an den Browser senden.

# http_server.py 

def do_POST(self): 
    # ... 
    result = socket_client.request(message) 
    self.send_response(200) 
    self.end_headers() 
    self.wfile.write(...) 

Und hier ist das, was ich in Anfrage zu tun versucht:

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 

Das Problem, das ich habe, ist, die Daten, die ich in der Request-Methode, die nach dem Sendemethode Aufruf scheinen durch die gestört zu werden Daten des Herzschlags im Thread.

Wenn ich den Heartbeat-Thread und den Empfangs-Thread auskommentiere, funktioniert die Request-Methode einwandfrei. Die Daten vom Server können fehlerfrei dekodiert werden und können erfolgreich an den Browser gesendet werden.

Meine Lösung könnte jetzt falsch sein und ich weiß wirklich nicht, wie ich diese Arbeit bekommen soll.

Jede Beratung geschätzt wird, Dank :)

Antwort

1

socket Objekt in Python ist, nicht Thread-sicher Sie die freigegebenen Ressourcen zugreifen müssen (in diesem Fall das Objekt) mit Hilfe einiger Synchronisierungsgrund, Wie threading.Lock in Python 2. Überprüfen Sie hier für ein ähnliches Problem: Python: Socket and threads?