La lettura da un flusso telnet in un array di byte di grandi dimensioni attende che l'array di byte sia pieno?
Domanda
Dalla lettura di alcune domande e risposte qui, sembra che un flusso di telnet non si chiuda davvero. L'uso di DataAvailable () non restituirà.
Ho ereditato del codice che ha richiesto molto tempo per essere completato e abbiamo pensato che fosse il server Telnet a costituire il problema. Tuttavia, esiste un byte [32757] in cui il codice tenta di memorizzare la risposta del server Telnet.
Qualcosa di simile al seguente:
Byte byteArray[] = new Byte[32757];
TcpClient sock = new TcpClient();
sock.GetStream().read(byteArray, 0 byteArray.length);
Se non ci sono 32757 byte o più, suppongo che questo codice aspetti fino a quando non vengono inviati abbastanza pacchetti vuoti per compensare la dimensione dell'array di byte. È corretto?
C'è un modo per verificare se il server Telnet ha finito di inviare tutto ciò che vuole? Non ci sono caratteri o stringhe di chiusura visibili in ogni "pagina" della sessione telnet.
Stavo pensando che un modo per correggere questo codice è leggere alcuni byte alla volta, aggiungerlo a una stringa, controllare la stringa per un carattere che termina o un set di caratteri e restituire se trovato. Altrimenti, leggi più byte, aggiungilo alla stringa e ricontrolla.
Suggerimenti?
Soluzione
No, Stream.Read
in genere non attende fino a quando non viene letto tutto ed è anche meno probabile che si verifichi un flusso di rete. Leggerà tutti i dati disponibili o si bloccherà fino a quando non saranno disponibili alcuni , ma è tutto.
Non esiste un vero concetto del server "finitura". inviare ciò che sta per inviare, a meno che:
- a) ti dice in anticipo quanto invierà
- b) indica quando ha finito con una sorta di dati di terminazione
- c) chiude la connessione
Potresti voler usare un timer di qualche tipo per ottenere un effetto di "continua a leggere fino a quando una delle letture impiega più di 5 secondi". Tieni presente che la lettura continuerebbe comunque: sceglieresti quel momento per aggiornare l'interfaccia utente (o qualsiasi altra cosa). È un argomento piuttosto complicato e devi davvero essere molto chiaro nella tua mente (e documenti!) Cosa vuoi fare e quale thread gestirà cosa.
Un'alternativa è impostare un timeout di lettura su TcpClient
, ma non ne ho esperienza. Probabilmente avresti solo bisogno di usare IOException
risultante in modo appropriato durante la lettura, ma non ho alcun consiglio da offrire al riguardo.
Altri suggerimenti
Oltre alla spiegazione di Jon Skeets un piccolo suggerimento:
poiché telnet è un protocollo basato su testo (riga), la lettura in byte [] significa che dovrai riassemblare il testo. Starai meglio con un TextReader:
System.IO.TextReader reader = new System.IO.StreamReader(
sock.GetStream(), Encoding.ASCII);
string line;
while ((line = reader.ReadLine()) != null) ...;
Sto indovinando qui che Telnet utilizza ASCII.