Domanda

Sto scrivendo un'applicazione web server in C # e utilizzo la classe StreamReader per leggere da un NetworkStream sottostante:

 NetworkStream ns = new NetworkStream(clientSocket);
 StreamReader sr = new StreamReader(ns);
 String request = sr.ReadLine();

Questo codice è soggetto ad attacchi DoS perché se l'attaccante non si disconnette mai non finiremo mai di leggere la riga. Esiste un modo per limitare il numero di caratteri letti da StreamReader.ReadLine () in .NET?

È stato utile?

Soluzione

Dovresti usare il sovraccarico Read (char [], int, int) (che limita la lunghezza) ed eseguire il tuo rilevamento di fine riga; non dovrebbe essere troppo complicato.

Per una versione leggermente pigra (che utilizza la versione di lettura a carattere singolo):

static IEnumerable<string> ReadLines(string path, int maxLineLength)
{
    StringBuilder currentLine = new StringBuilder(maxLineLength);
    using (var reader = File.OpenText(path))
    {
        int i;
        while((i = reader.Read()) > 0) {
            char c = (char) i;
            if(c == '\r' || c == '\n') {
                yield return currentLine.ToString();
                currentLine.Length = 0;
                continue;
            }
            currentLine.Append((char)c);
            if (currentLine.Length > maxLineLength)
            {
                throw new InvalidOperationException("Max length exceeded");
            }
        }
        if (currentLine.Length > 0)
        {
            yield return currentLine.ToString();
        }                
    }
}

Altri suggerimenti

Potrebbe essere necessario uno dei sovraccarichi StreamReader.Read :

Tratto da http://msdn.microsoft.com/en-us /library/9kstw824.aspx

    using (StreamReader sr = new StreamReader(path)) 
    {
        //This is an arbitrary size for this example.
        char[] c = null;

        while (sr.Peek() >= 0) 
        {
            c = new char[5];
            sr.Read(c, 0, c.Length);
            //The output will look odd, because
            //only five characters are read at a time.
            Console.WriteLine(c);
        }
    }

Concentrati sulla riga sr.Read (c, 0, c.Length) . Questo legge solo 5 caratteri dallo stream e inseriti nell'array c . È possibile che si desideri modificare 5 per il valore desiderato.

Ecco la mia soluzione basata sulla soluzione di Marc Gravell:

using System;
using System.IO;
using System.Text;

namespace MyProject
{
    class StreamReaderExt : StreamReader
    {

        public StreamReaderExt(Stream s, Encoding e) : base(s, e)
        {            
        }

        /// <summary>
        /// Reads a line of characters terminated by CR+LF from the current stream and returns the data as a string
        /// </summary>
        /// <param name="maxLineLength">Maximum allowed line length</param>
        /// <exception cref="System.IO.IOException" />
        /// <exception cref="System.InvalidOperationException">When string read by this method exceeds the maximum allowed line length</exception>
        /// <returns></returns>
        public string ReadLineCRLF(int maxLineLength)
        {
            StringBuilder currentLine = new StringBuilder(maxLineLength);

            int i;
            bool foundCR = false;
            bool readData = false;

            while ((i = Read()) > 0)
            {

                readData = true;

                char c = (char)i;

                if (foundCR)
                {
                    if (c == '\r')
                    {
                        // If CR was found before , and the next character is also CR,
                        // adding previously skipped CR to the result string
                        currentLine.Append('\r');
                        continue;
                    }
                    else if (c == '\n')
                    {
                        // LF found, finished reading the string
                        return currentLine.ToString();
                    }
                    else
                    {
                        // If CR was found before , but the next character is not LF,
                        // adding previously skipped CR to the result string
                        currentLine.Append('\r');
                        foundCR = false;
                    }
                }
                else // CR not found
                {
                    if (c == '\r')
                    {
                        foundCR = true;
                        continue;
                    }
                }

                currentLine.Append((char)c);
                if (currentLine.Length > maxLineLength)
                {
                    throw new InvalidOperationException("Max line length exceeded");
                }
            }

            if (foundCR)
            {
                // If CR was found before, and the end of the stream has been reached, appending the skipped CR character
                currentLine.Append('\r');
            }

            if (readData)
            {
                return currentLine.ToString();
            }

            // End of the stream reached
            return null;

        }
    }
}

Questa parte di codice è fornita "COSÌ COM'È" senza NESSUNA GARANZIA.

Puoi sempre utilizzare " .Leggi (...) " e MSDN consiglia di farlo per una situazione come la tua.

http://msdn.microsoft.com/en-us/library/system .io.streamreader.readline.aspx

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