Search code examples
c#tcpstreamreadernetworkstreamnntp

StreamReader doesn't retrieve everything from NetworkStream (TCP and C#)


I'm working on a project, where you have to retrieve data from a server and display it in the UI. It's a newsgroups server, that contains about 250 groups in total.

The output from the server SHOULD as far as I understand, be stored in a NetworkStream object and is read from a StreamReader which saves each line into a string.

This works, but unfortunately it seems like it doesn't finish reading everything before finishing the method call.

Next time I call another command and read it from the StreamReader it then returns the rest of the output from the previous command.

I've been struggling with this for hours now, and can't see how to fix this.

This is my code:

    public ObservableCollection<Newsgroup> GetNewsGroups()
    {
        ObservableCollection<Newsgroup> newsgroups = new ObservableCollection<Newsgroup>();

        if(connectionStatus.Equals(ConnectionStatus.CONNECTED) && loginStatus.Equals(LoginStatus.LOGGED_IN))
        {

            byte[] sendMessage = Encoding.UTF8.GetBytes("LIST\n");

            // Write to the server 
            ns.Write(sendMessage, 0, sendMessage.Length);
            Console.WriteLine("Sent {0} bytes to server...", sendMessage.Length);

            ns.Flush();

            // b) Read from the server
            reader = new StreamReader(ns, Encoding.UTF8);

            // We want to ignore the first line, as it just contains information about the data
            string test = reader.ReadLine();

            Console.WriteLine(test);

            string recieveMessage = "";

            if (ns.CanRead)
            {

                while (reader.Peek() >= 0)
                {

                    recieveMessage = reader.ReadLine();
                    Console.WriteLine("Got this message {0} back from the server", recieveMessage);
                    // This part will simply remove the annoying numbers after the newsgroup name
                    int firstSpaceIndex = recieveMessage.IndexOf(" ");
                    string refactoredGroupName = recieveMessage.Substring(0, firstSpaceIndex);
                    newsgroups.Add(new Newsgroup { GroupName = refactoredGroupName });
                }

            }

        }

        return newsgroups;

    }

Solution

  • I'd be interested to see what information about the data you are throwing away on the first line (what's in "test" variable). If it tells you how many bytes are coming your way, you should use that information to retrieve the correct amount of data instead of Peek.

    If the last line contains a single period, change your while loop to look like this instead:

    recieveMessage = reader.ReadLine();
    while (recieveMessage != ".")
    { 
        Console.WriteLine("Got this message {0} back from the server", recieveMessage); // This part will simply remove the annoying numbers after the newsgroup name int 
        firstSpaceIndex = recieveMessage.IndexOf(" "); 
        string refactoredGroupName = recieveMessage.Substring(0, firstSpaceIndex);
        newsgroups.Add(new Newsgroup { GroupName = refactoredGroupName }); 
        recieveMessage = reader.ReadLine();
    }