2015-06-03 2 views
6

Sto scrivendo un modulo Python che sta comunicando con un programma go tramite socket unix. Il client (il modulo python) scrive i dati sul socket e il server li consuma.Presa Python chiusa prima che tutti i dati siano stati consumati dal telecomando

# Simplified version of the code used 
outputStream = socket.socket(socketfamily, sockettype, protocol) 
outputStream.connect(socketaddress) 
outputStream.setblocking(True) 
outputStream.sendall(message) 
.... 
outputStream.close() 

Il mio problema è che il cliente Python tende a finire e chiudere il socket prima che i dati sono stati effettivamente letto dal server che porta ad un "tubo rotto, ripristinato il collegamento dal pari" sul lato server. Qualsiasi cosa faccia, per il codice Python tutto è stato inviato e così le chiamate a send() sendall() select() sono tutti di successo ...

Grazie in anticipo

EDIT: non posso usare arresto a causa di Mac OS

EDIT2: ho anche provato a rimuovere il timeout e chiamare setblocking (vero), ma non cambia nulla

Edit3: Dopo pronto questo problema http://bugs.python.org/issue6774 sembra che la documentazione non è necessaria spaventoso così ho ripristinato lo spegnimento ma ho ancora lo stesso problema:

# Simplified version of the code used 
outputStream = socket.socket(socketfamily, sockettype, protocol) 
outputStream.connect(socketaddress) 
outputStream.settimeout(5) 
outputStream.sendall(message) 
.... 
outputStream.shutdown(socket.SHUT_WR) 
outputStream.close() 

risposta

0

IHMO questo è fatto meglio con una libreria/framework di I/O Asynchornous. Ecco una soluzione del genere usando circuits:

Il server esegue l'echo su ciò che riceve sullo stdout e il client apre un file e lo invia al server in attesa che venga completato prima di chiudere il socket e terminarlo. Questo viene fatto con un misto di Async I/O e Coroutine.

server.py:

from circuits import Component 
from circuits.net.sockets import UNIXServer 

class Server(Component): 

    def init(self, path): 
     UNIXServer(path).register(self) 

    def read(self, sock, data): 
     print(data) 

Server("/tmp/server.sock").run() 

client.py:

import sys 

from circuits import Component, Event 
from circuits.net.sockets import UNIXClient 
from circuits.net.events import connect, close, write 

class done(Event): 
    """done Event""" 

class sendfile(Event): 
    """sendfile Event""" 

class Client(Component): 

    def init(self, path, filename, bufsize=8192): 
     self.path = path 
     self.filename = filename 
     self.bufsize = bufsize 

     UNIXClient().register(self) 

    def ready(self, *args): 
     self.fire(connect(self.path)) 

    def connected(self, *args): 
     self.fire(sendfile(self.filename, bufsize=self.bufsize)) 

    def done(self): 
     raise SystemExit(0) 

    def sendfile(self, filename, bufsize=8192): 
     with open(filename, "r") as f: 
      while True: 
       try: 
        yield self.call(write(f.read(bufsize))) 
       except EOFError: 
        break 
       finally: 
        self.fire(close()) 
        self.fire(done()) 

Client(*sys.argv[1:]).run() 

Nel mio test di questa si comporta esattamente come mi aspetto che senza gli errori e i server ricevono il file completo prima che il client claschi il socket e si chiuda.