Domanda

Semplicemente ho cercato di implementare cosa BufferedStreamReader fa in Java.Ho un socket stream aperto e voglio solo leggerlo in modo orientato alla riga, riga per riga.

Ho il seguente codice server.

while (continueProcess)
        {
            try
            {
                StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8);
                string command = reader.ReadLine();
                if (command == null)
                    break;

                OnClientExecute(command);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

E il seguente codice cliente:

TcpClient tcpClient = new TcpClient();
        try
        {
            tcpClient.Connect("localhost", serverPort);
            StreamWriter writer = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8);
            writer.AutoFlush = true;
            writer.WriteLine("login>user,pass");
            writer.WriteLine("print>param1,param2,param3");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
        finally
        {
            tcpClient.Close();
        }

Il server legge solo la prima riga (login>user,pass) poi ReadLine restituisce null!

Qual è il modo più semplice per ottenere questo lettore orientato alla riga come in Java BufferedStreamReader?:S

È stato utile?

Soluzione

Un tipico lettore di riga è qualcosa del tipo:

using(StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8)) {
    string line;
    while((line = reader.ReadLine()) != null) {
        // do something with line
    }
}

(notare la using per garantire noi Dispose() anche se riceviamo un errore e il ciclo)

Se vuoi, puoi astrarre questo (separazione delle preoccupazioni) con un blocco iteratore:

static IEnumerable<string> ReadLines(Stream source, Encoding encoding) {
    using(StreamReader reader = new StreamReader(source, encoding)) {
        string line;
        while((line = reader.ReadLine()) != null) {
            yield return line;
        }
    }
}

(nota che lo abbiamo spostato in una funzione e rimosso "fai qualcosa", sostituendolo con "yield return", che crea un iteratore (una macchina a stati iterata pigramente e senza buffering)

Lo consumeremmo quindi semplicemente come:

foreach(string line in ReadLines(Socket.GetStream(), Encoding.UTF8)) {
    // do something with line
}

Ora il nostro codice di elaborazione non deve preoccuparsi Come leggere le righe - semplicemente dato una sequenza di righe, fai qualcosa con esse.

Si noti che il using (Dispose()) si applica a TcpClient pure;dovresti prendere l'abitudine di controllare IDisposable;ad esempio (inclusa ancora la registrazione degli errori):

using(TcpClient tcpClient = new TcpClient()) {
    try {
       tcpClient.Connect("localhost", serverPort);
       StreamWriter writer = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8);
       writer.AutoFlush = true;
       writer.WriteLine("login>user,pass");
       writer.WriteLine("print>param1,param2,param3");
    } catch (Exception ex) {
        Console.Error.WriteLine(ex.ToString());
    }
}

Altri suggerimenti

La mentre nel codice del server è configurato per leggere una sola riga per ogni connessione. Avrete bisogno di un altro, mentre all'interno della provare a leggere tutte le linee di essere inviato. Penso che una volta che il flusso è installato sul lato client, si sta per inviare tutti i dati. Poi sul lato server, il tuo stream è efficace solo la lettura di una riga da quel particolare flusso.

provato questo e ha ottenuto

Il tipo o dello spazio dei nomi il nome 'flusso' non è stato trovato (che le manca un un riferimento all'assembly direttiva using o?) Il tipo o dello spazio dei nomi il nome 'StreamReader' non è stato trovato (che le manca un un riferimento all'assembly direttiva using o?) Il tipo o dello spazio dei nomi il nome 'StreamReader' non è stato trovato (che le manca un un riferimento all'assembly direttiva using o?) 'System.Net.Sockets.Socket' non contiene una definizione per 'GetStream'

    public string READS()
    {
        byte[] buf = new byte[CLI.Available];//set buffer
        CLI.Receive(buf);//read bytes from stream
        string line = UTF8Encoding.UTF8.GetString(buf);//get string from bytes
        return line;//return string from bytes
    }
    public void WRITES(string text)
    {
        byte[] buf = UTF8Encoding.UTF8.GetBytes(text);//get bytes of text
        CLI.Send(buf);//send bytes
    }

CLI è una presa. per alcuni Rezone la classe TcpClient non funziona bene sul mio pc più, ma la classe Socket funziona bene.

UTF-8 è lo StreamReader / scrittura codifica stranded

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top