0

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;

    }

1 Answers1

1

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();
}
crwells
  • 81
  • 4
  • Oh it doesn't contain any relevant information about the bytes. It's just the first line given from the server, which in this case is: 215 Newsgroups in form "group high low flags". – Lukas Méndez Duus Oct 23 '19 at 13:20
  • Is there anything unique about the last byte of data sent in the list? Most lines clearly end with a newline...is there anything special about the very last line of data we could use? – crwells Oct 23 '19 at 13:21
  • An awful way you might have to use is that when Peek returns 0, sleep for some period of time and then check it again. If you don't get anything after a second, then maybe you are completely finished. – crwells Oct 23 '19 at 13:24
  • It's just the rest of the newsgroups. I'm not sure if I understand you correctly. Could for example be these few lines: Got this message soc.culture.celtic 0000066255 0000066171 y back from the server Got this message soc.culture.chile 0000157708 0000157643 y back from the server Got this message soc.culture.china 0001020018 0000994871 y back from the server Got this message soc.culture.colombia 0000189192 0000189116 y back from the server Got this message soc.culture.cornish 0000009648 0000009569 y back from the server – Lukas Méndez Duus Oct 23 '19 at 13:24
  • Any idea what the "y" at the end means? You said that if you make another call, the rest of the data will be on the network stream. What's that data look like? I'm looking for the very last one...like maybe it would have an "n" or something at the end instead of a "y". Is the server you are reading this from publicly accessible so I could try connecting to it? – crwells Oct 23 '19 at 13:27
  • It requires a login. The last line just contains a "." (dot) – Lukas Méndez Duus Oct 23 '19 at 13:29
  • Try the code in my edited answer (you might need to trim the string before comparing for ".") – crwells Oct 23 '19 at 13:35
  • Jesus Christ, why didn't I think of that. Time to take a coffee break! THANK YOU SO MUCH! – Lukas Méndez Duus Oct 23 '19 at 13:40
  • But what should I do in cases, where there's no dot at the end? – Lukas Méndez Duus Oct 23 '19 at 15:58
  • I think it would just depend. If there was absolutely nothing to indicate the end of the data, then I would try the "Peek()" mechanism -- and when it looks like no more data is present, sleep for 100 ms and check again. Do this up to 10 times (total 1 seconds) just to make sure there isn't any other data coming. What "Peek()" is telling you is if there is data ready to be read. But maybe there was a network slowdown, and you just need to wait for a bit until more data is ready. So maybe you want to wait up to 2-5 seconds just to make sure. – crwells Oct 23 '19 at 16:13