Search code examples
c#socketstcpclientstreamreaderreadline

StreamReader - ReadLine from Socket doesn't stop


I'm trying to communicate with a server.

This is my simple code:

System.Net.Sockets.TcpClient sock = new System.Net.Sockets.TcpClient();
string outputString = string.Empty;
sock.Connect("stack.overflow", 80);

NetworkStream ns = null;
StreamReader sr = null;
StreamWriter sw = null;

ns = sock.GetStream();
sr = new StreamReader(ns);
sw = new StreamWriter(ns) { NewLine = "\r\n", AutoFlush = true };
ns.ReadTimeout = 10;
sw.WriteLine("send data to server");
sw.Flush();

outputString = sr.ReadLine();
while (!string.IsNullOrEmpty(outputString))
{
    System.Diagnostics.Debug.WriteLine(outputString);
    outputString = sr.ReadLine();
}

(I know my code has room for improvement. It kept it simple for my test)

Everything works fine beside the ReadLine(). It doesn't do what I'm expecting it to do.

It reads all lines from the server and after the last line it just endlessly waits for a new line. At least for me it seems like it is waiting.

I thought it would stop after the last line and return null or something else.

Can someone explain me what the best practice is to get all lines from the server and move on?


Solution

  • I solved it like this:

    public class ServerHandler
    {
        private BackgroundWorker serverWorker = new BackgroundWorker();
        public event EventHandler ServerResponse;
    
        private TcpClient socket;
        private NetworkStream networkStream;
        private StreamReader streamReader;
        private StreamWriter streamWriter;
    
        public ServerHandler()
        {
            System.Net.Sockets.TcpClient sock = new System.Net.Sockets.TcpClient();
    
            serverWorker.WorkerSupportsCancellation = true;
            serverWorker.DoWork += new DoWorkEventHandler(serverWorker_DoWork);
        }
    
        public void ConnectToServer()
        {
            socket = new TcpClient();
            socket.Connect("stack.overflow", 80);
    
            networkStream = socket.GetStream();
            streamReader = new StreamReader(networkStream);
            streamWriter = new StreamWriter(networkStream) { NewLine = "\r\n", AutoFlush = true };
    
            SendMessage("some data");
        }
    
        public bool IsConnected
        {
            get { return socket.Connected; }
        }
    
        public void StartListening()
        {
            if (ServerResponse == null)
                throw new Exception("There is no event to intercept the response!");
    
            serverWorker.RunWorkerAsync();
        }
    
        private void SendMessage(string message)
        {
            streamWriter.WriteLine(message);
            streamWriter.Flush();
        }
    
        private void serverWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
    
            while (true)
            {
                string serverResponse = streamReader.ReadLine();
    
                ServerResponse(serverResponse, new EventArgs());
            }
        }
    }
    

    Like willaien already said, the stream doesn't know when it ends. As long as you are communicating with the server you can wait for a response.

    I put the code that listens to the server in a background worker, that always listens and that sends an event, when a new response appears.