Come gestire un'app client che si connette a un server TCP e invia / riceve i dati di testo in modo bidirezionale?

3

Ho una domanda concettuale (che probabilmente è meglio pubblicata qui che su StackOverflow?).

Voglio sviluppare un'applicazione client che mantenga una connessione persistente a un server e scambia i dati di testo avanti e indietro. Un client IRC è un ottimo esempio. Quindi, questi sono dati:

  1. C'è un flusso abbastanza costante di testo in entrata che deve essere interpretato e gestito in qualche modo dal client.
  2. Il client invierà comandi e si aspetta risposte formattate in modo specifico dal server.

Ci sono probabilmente parecchi approcci, ma sto cercando (ovviamente) il più efficiente. Dovrei semplicemente gestire tutto il testo in arrivo attraverso l'evento "on data received"?

(pseudo-codice)

on(data)
  if data matches /###DAT action1/
    handleAction1
  else if data matches /###DAT action2/
    handleAction2
  else if data matches /###DAT PRIVMSG/
    handlePrivateMessage
  else if data matches /###DAT LOGIN_OK/
    handleConfirmedLogin

Quindi ogni possibile bit di testo che vorrei trattare, viene scansionato qui, sia che si tratti di un messaggio privato di qualcuno, sia di una risposta a un comando di login che ho appena inviato.

C'è un modo migliore per affrontare questo? Se è importante, sto usando JavaScript.

    
posta ffxsam 11.01.2016 - 04:33
fonte

1 risposta

1

È probabile che l'approccio più efficiente sia quello di modellare il gestore dei messaggi come una macchina a stati. Scansione carattere per carattere e passare a uno stato appropriato. Se non è stata definita una transizione di stato per un carattere, il messaggio non è valido. Se il nuovo stato è definitivo (un messaggio completo), quindi eseguire l'azione prescritta. Fino ad allora, continua a elaborare carattere per carattere. Fondamentalmente, è un messaggio lexer con un solo token da identificare. (Puoi sempre aggiungere altri parametri, o quant'altro, in fondo alla strada. Lexing rimarrà veloce.) Il vantaggio di questo approccio è che tu tocchi una volta sola ogni carattere nel messaggio. Nel tuo pseudo-codice, se il messaggio è LOGIN_OK , tocchi il primo carattere quattro volte prima che sia risolto.

Diamo un'occhiata a un esempio. Di 'che i nostri messaggi validi sono:

ACTION_1
ACTION_2
PRIVMSG
LOGIN_OK

Inizia la scansione dei caratteri da sinistra a destra. Se vedo una "L", so immediatamente che il messaggio deve essere LOGIN_OK o non valido. Non è necessario prendere in considerazione gli altri casi. Continua a scansionare per confermare.

Se il primo personaggio che vedo è "A", so che il messaggio deve essere un'azione. Non è necessario considerare PRIVMSG o LOGIN_OK . Ho bisogno di consumare "A", "C", "T", "I", "O", "N" e "_" prima di arrivare a un personaggio che risolve l'ambiguità. La cosa bella è che una volta arrivato lì, ho finito. O so che la risposta o il messaggio non è valido.

Considera il messaggio ACTION_INVALID nel tuo approccio if/else . È necessario eseguire la scansione dell'intero messaggio per verificare la presenza di ACTION_1 , quindi eseguire nuovamente la scansione dell'intero messaggio per verificare la presenza di ACTION_2 . Anche allora, devi considerare la possibilità di PRIVMSG o LOGIC_OK . Con una macchina di stato / lexer, il primo personaggio elimina immediatamente due possibilità. Per risolvere completamente il messaggio, devi solo guardare otto caratteri rispetto alla scansione della stringa ancora e ancora.

Se decidi di seguire questa strada, strumenti come Ragel sono utili per generare la macchina di stato rispetto alla scrittura a mano. C'è anche una porta che genera JavaScript .

    
risposta data 11.01.2016 - 14:22
fonte

Leggi altre domande sui tag