read-loop from TCP/IP

I need to connect a server (with ip and port) and create a read-loop that will get messages from the server as XML. sometimes there are no messages from the server.

I tried to create a connection (works fine) and read messages, I get the first message from the server and when I'm trying to read another one - it get stuck. I think that maybe there are no messages right now but I need that the loop will continue until there will be messages... it doesn't even go to "catch" or "finally", just do nothing..

public class Connection
{
    public Connection()
    {
        Socket server = null;
        try
        {
            string p = string.Empty;
            using (var client = new TcpClient(myIPAddress, myPort))
            using (var stream = client.GetStream())
            using (var reader = new StreamReader(stream))
            {
               while (p != null)
               {
                    try
                    {
                        p = reader.ReadLine();
                    }
                    catch (Exception e)
                    {
                       //
                    }
               }
            }
        }
        catch (Exception e)
        {
            //
        }
        finally { 
            server.Close(); 
        }
    }
}

Answers


The loop is continuing, waiting for data. The issue here seems to be simply that ReadLine() is a blocking call. You mention that there might not be a message yet; well, ReadLine() is going to block until one of two conditions is met:

  • it can successfully read some data, terminated by a newline (or EOF, i.e. a message without a newline followed by socket closure) - in which case it returns the line of data
  • no more data is received and the stream is closed, in which case it returns null

So basically, ReadLine() is going to wait until either a message comes in, or the socket is closed. That is simply the behaviour of ReadLine(). If that is problematic, you could work closer to the socket, and check NetworkStream.DataAvailable but: note that only tells you if some data is currently available; it doesn't mean "this is an entire message", nor can it be used to tell if more messages will arrive. The main use of DataAvailable is to decide between sync and async access. Plus if you work close to the socket you'll have to do all your own buffering and encoding/decoding.

It looks to me like ReadLine() is working successfully. The only thing I would do here is re-phrase it a bit:

string line;
while((line = reader.ReadLine()) != null) {
    // line is meaningful; do something
}

One last thought: xml is not always trivially split into messages simply on a "per-line" basis. You might want to consider some other form of framing, but that may well mean working closer to the socket, rather than a StreamReader.


You have to wait till data arrives at the stream, you could try using follwing,

if(reader.EndOfStream)
   continue;

Need Your Help

Building command strings using variables with various quote levels and spaces

bash variables quotes spaces

I have a script that runs curl. I want to be able to optionally add a -H parameter, if a string isn't empty. What's complex is the levels of quoting and spaces.

jquery token-input and active_admin

jquery ruby-on-rails-3 ruby-on-rails-3.1 activeadmin

I want to use jquery-token-input with has_many relationship inside active_admin.