2009-10-31 25 views
9

Ho scritto un server in Python che ha lo scopo di inviare dati al client nel formato "Intestazione: Messaggio"Come svuotare i socket Python?

Vorrei poter inviare ciascun messaggio singolarmente in modo che il client abbia bisogno di eseguire il lavoro minimo per leggere la "intestazione" e il "messaggio"

Sfortunatamente, non riesco a capire come svuotare correttamente un socket python così quando ho più mandate eseguite in rapida successione i messaggi vengono raggruppati insieme nel buffer socket e inviato come un grosso pezzo.

Esempio:

Server invia ...

socket.send ("header1:message1") 
socket.send ("header2:message2") 
socket.send ("header3:message3") 

Cliente riceve ... "header1: message1header2: message2header3: Message3"

vorrei ricevere tre messaggi individuali

header1:message1 
header2:message2 
header3:message3 

Ho bisogno di un modo per svuotare dopo eac h invia

+0

duplicato esatto: http://stackoverflow.com/questions/1097974/how-to-flush-a-socket-in-python – ChristopheD

+4

* Non un duplicato : * Il titolo è * letteralmente * un duplicato, ma la domanda è in realtà * funzionalmente * diversa. L'OP ha bisogno di una risposta proprio come @ebo qui sotto. –

+1

Oops, sembra corretto. Cercherò di essere un po 'più lento la prossima volta ;-) – ChristopheD

risposta

19

Immagino che tu stia parlando su una connessione TCP.

Il tuo approccio è imperfetto. Un flusso TCP è definito come un flusso di byte. È sempre necessario utilizzare una sorta di separatore e non si può fare affidamento sullo stack di rete per separare i messaggi.

Se davvero avete bisogno di servizi basati su datagramma passare a UDP. In tal caso, dovrai gestire personalmente la ritrasmissione.

per chiarire:

Lavaggio del buffer di invio di solito crea nuovi pacchetti, proprio come ci si aspetta. Se il tuo client legge questi pacchetti abbastanza velocemente potresti ricevere un messaggio per lettura.

Ora immagina di comunicare tramite un collegamento satellitare. A causa dell'elevata larghezza di banda e della latenza, l'ultimo router prima del sat attende un breve intervallo di tempo finché nel buffer non ci sono abbastanza dati e invia tutti i pacchetti contemporaneamente. Il tuo client ora riceverà tutti i pacchetti senza ritardi e inserirà tutti i dati nel buffer di ricezione in una sola volta. Quindi la tua separazione è andata di nuovo.

+0

+1: aggiungerei per il bene di Edumacations che, anche se @Jah fosse per svuotare le prese, il suo client avrebbe comunque ricevuto i messaggi esattamente allo stesso modo - lo svuotamento è sulla cancellazione dei buffer nel nome della riduzione della latenza e * non * delimitazione dei messaggi. –

+0

Fornito uno scenario per mostrare come ciò potrebbe andare storto. thx @ stu – ebo

+0

+1: TCP è uno stream. La tempistica dei dati TCP viene specificamente eliminata dall'internet routing e dal protocollo TCP. I dati devono essere memorizzati nel buffer; "flushing" in realtà non significa molto. Tutto ciò significa che i dati sono fuori dai buffer della tua app e nel buffer del protocollo TCP. –

0

Quello che stai cercando di fare è dividere i tuoi dati in "lotti".

Ad esempio, si opera su "batch" ogni volta che si leggono "righe" su un file. Cosa definisce una "linea"? È una sequenza di byte terminata da '\ n'. Un altro esempio è: leggete 64KiB "pezzi" da un file. Cosa definisce un "pezzo"? Lo fai, dal momento che hai letto 65536 byte ogni volta. Vuoi un "pezzo" di lunghezza variabile? Hai appena prefisso il tuo "pezzo" con le sue dimensioni, poi leggi il "pezzo". i file "aiff" (le cui implementazioni sono anche i file .wav e .avi di MS Windows) e i file "mov" sono organizzati in questo modo.

Questi tre metodi sono i metodi fondamentali per organizzare un flusso di byte qualunque supporto:

  1. separatori registrare
  2. registra dimensione fissa
  3. registra prefisso con le loro dimensioni.

Possono essere miscelati e/o modificati. Ad esempio, potresti avere "separatori di record variabili", come un lettore XML: leggi byte dal primo '<' fino al primo '>', aggiungi una barra dopo il primo '<' e chiamalo end-of-record, leggi stream fino a end-of-record. Questa è solo una descrizione approssimativa.

Scegliere un metodo e implementarlo sia nello scrittore che nel lettore. Se documenti anche le tue scelte, hai appena definito il tuo primo protocollo.

3

basta aggiungere \ n dopo ogni messaggio ... come

socket.send ("header1: message1 \ n")

socket.send ("header2: Message2 \ n")

socket.send ("header3: Message3 \ n")

+1

Questo ha funzionato per me! –

+0

"\ n" non garantisce che i messaggi siano separati. – crey4fun