9

I am trying to interface an ancient network camera to my computer and I am stuck at a very fundamental problem -- detecting the end of stream.

I am using TcpClient to communicate with the camera and I can actually see it transmitting the command data, no problems here.

        List<int> incoming = new List<int>();            
        TcpClient clientSocket = new TcpClient();
        clientSocket.Connect(txtHost.Text, Int32.Parse(txtPort.Text));
        NetworkStream serverStream = clientSocket.GetStream();
        serverStream.Flush();

        byte[] command = System.Text.Encoding.ASCII.GetBytes("i640*480M");
        serverStream.Write(command, 0, command.Length);

Reading back the response is where the problem begins though. I initially thought something simple like the following bit of code would have worked:

        while (serverStream.DataAvailable)
        {
            incoming.Add(serverStream.ReadByte());
        }

But it didn't, so I had a go another version this time utilising ReadByte(). The description states:

Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream.

so I thought I could implement something along the lines of:

        Boolean run = true;
        int rec;
        while (run)
        {
            rec = serverStream.ReadByte();

            if (rec == -1)
            {
                run = false;
                //b = (byte)'X';
            }
            else
            {
                incoming.Add(rec);
            }

        }

Nope, still doesn't work. I can actually see data coming in and after a certain point (which is not always the same, otherwise I could have simply read that many bytes every time) I start getting 0 as the value for the rest of the elements and it doesn't halt until I manually stop the execution. Here's what it looks like: data

So my question is, am I missing something fundamental here? How can I detect the end of the stream?

Many thanks,

H.

Hamza
  • 2,313
  • 7
  • 25
  • 33
  • You're reading a byte from the stream, a byte can't be -1. – Alex McBride Jun 29 '11 at 15:09
  • Just brainfarting here, but could be that there is no end of stream, that it just keeps transmitting data, and the 0's are sort of a KeepAlive signal or something. Another thought might be, that the 0 is the end of stream. Compare it to the rest of the data you get, if you only see non-zero values, then you can assume 0 is the EOS signal from the camera. If you do see a few zero values, just detect whenever you get 4 or 8 zeroes in a row. Dunno if any of this is useful, which is why I'm just making a comment. – William Jun 29 '11 at 15:10
  • 3
    According to the documentation `ReadByte()` actually returns an int. – Hamza Jun 29 '11 at 15:10
  • @MindWorX: I haven't thought of KeepAlive TBH, thanks. Sadly I do have occasions where I get a bunch of zeroes in the data so not sure if I can use that method to detect end of frame. – Hamza Jun 29 '11 at 15:12
  • Well, like @The Evil Greebo suggests below, you need to find some patterns in the stream. I'd suggest you read a chunk. Maybe 1kb of data or whatever fits most packages, and then do a side by side hex compare, to see what's common, especially at the end, before all the zeroes start. – William Jun 29 '11 at 15:21
  • Check if the length is prepended in the data you received. Until you know the length you can't really be sure. The server may send the data in > 1 transactions. – jfs Jun 29 '11 at 15:27

2 Answers2

17

What you're missing is how you're thinking of a TCP data stream. It is an open connection, like an open phone line - someone on the other end may or may not be talking (DataAvailable), and just because they paused to take a breath (DataAvailable==false) it doesn't mean they're actually DONE with their current statement. A moment later they could start talking again (DataAvailable==true)

You need to have some kind of defined rules for the communication protocol ABOVE TCP, which is really just a transport layer. So for instance perhaps the camera will send you a special character sequence when it's current image transmission is complete, and so you need to examine every character sent and determine if that sequence has been sent to you, and then act appropriately.

Ian R. O'Brien
  • 6,682
  • 9
  • 45
  • 73
The Evil Greebo
  • 7,013
  • 3
  • 28
  • 55
  • 1
    Thanks, I think I might have found a way of doing this going by the resolution I use to acquire frames. – Hamza Jun 29 '11 at 16:25
2

Well you can't exactly says EOS on a network communication ( unless the other party drop the connection ) usually the protocol itself contains something to signal that the message is complete ( sometimes a new line, for example ). So you read the stream and feed a buffer, and you extract complete message by applying these strategies.

Felice Pollano
  • 32,832
  • 9
  • 75
  • 115