I am using a Socket to receive data via TCP, and TextReader.ReadLine to read lines from the connection. There is a problem where a full line has not been received — TextReader.ReadLine returns an incomplete string. I want it to return null, indicating that a full line could not be read. How can I do this?
Basically, I have this data incoming:
'hello\nworld\nthis is a test\n'
When I run ReadLine I get these in return:
'hello' 'world' 'this is a te' <null> <socket gets more data> 'st' <null>
I do not want ‘this is a te’ returned. Rather, I want ‘this is a test’ to wait until the entire line has been received.
Code:
var endPoint = ...; var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); socket.Connect(endPoint); var stream = new NetworkStream(socket, true); var messageBuffer = new StringBuilder(); // Data received async callback (called several times). int bytesRead = stream.EndRead(result); string data = Encoding.UTF8.GetString(readBuffer.Take(bytesRead).ToArray()); messageBuffer.Append(data); using(var reader = new StringReader(messageBuffer.ToString())) { // This loop does not know that Message.Read reads lines. For all it knows, it could read bytes or words or the whole stream. while((Message msg = Message.Read(reader)) != null) // See below. { Console.WriteLine(msg.ToString()); // See example input/echo above. } messageBuffer = new StringBuilder(reader.ReadToEnd()); } // Method of Message. public static Message Read(TextReader reader) { string line = reader.ReadLine(); if(line == null) return null; return Message.FromRawString(line); }
Thanks.
I decided to write my own ReadLine parser-ish kinda thing. Here’s the code:
Many thanks to @Jon Skeet, @Noldorin, and @Richard for their very helpful suggestions. Your combined efforts led me to my final solution. =]