0

I'm using Unity and .NET to create a TCP client-server relationship.

I actually have everything working where I can send messages back and forth, but now I am hitting a NullReferenceException that is got me scratching my head.

I have a function in my TCPClientListener in my Unity code that calls ReadSocket every Update()

public void SetupSocket(){
      socket = new TcpClient(host, port);
      stream = socket.GetStream();
      writer = new StreamWriter(stream);
      reader = new StreamReader(stream);
      socketReady = true;

}

public string ReadSocket(){
   if(stream.DataAvailable){
      return "New Data! " + reader.ReadLine().Replace("<EOF>", "");
   }
   return "";
}

The above works fine, no problem. WHen the server sends a message, I receive it just fine. But then I add a very simple if statement, and now I'm getting NullReferenceException in regards to reader.

public string ReadSocket() {
        if (stream.DataAvailable) {
            if (reader.ReadLine().Contains("<EOF>"))
                return "New data! " + reader.ReadLine().Replace("<EOF>", "");
        }
        return "";
    }

I hope that I have just been looking at this too long to see the obvious. Why does

if (reader.ReadLine().Contains("<EOF>"))

give me an error!? If I remove it, no error..

Ron Beyer
  • 11,003
  • 1
  • 19
  • 37
user3822370
  • 641
  • 7
  • 20
  • possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Bjørn-Roger Kringsjå Aug 09 '15 at 15:47

1 Answers1

3

The immediate bug is that you are reading two lines. The second read appears to return null. You could have found this by applying standard NRE debugging techniques.

Another bug is that you assume that TCP preserves bessage boundaries. If DataAvailable > 0 this does not mean that an entire line is available. There might be just one byte available. You might find your game blocking unexpectedly.

Usually, it is best to have a continuous read loop running and never pool for data. Just read. When a new line is received act on it.

usr
  • 168,620
  • 35
  • 240
  • 369
  • Oh I see. I added string line = reader.ReadLine(); Thanks. Also I cannot find anything on Google about NRE. – user3822370 Aug 09 '15 at 15:50
  • NRE = NullReferenceException – usr Aug 09 '15 at 16:03
  • /facepalm, right. `There might be just one byte available` that's why I am checking for – user3822370 Aug 09 '15 at 16:17
  • What do you think happens when DataAvailable = 1 and the incoming data is "x"? Then your UI is blocked in the ReadLine call until the rest of the string comes in. That can be a long time later. – usr Aug 09 '15 at 16:28
  • Then what do I do? I guess just keep reading data, and building it into a string, then using another loop (or same loop) to see if that string has EOF ? – user3822370 Aug 10 '15 at 01:14
  • Look at the last paragraph. Have a reading loop in a background task that pulls lines from the reader. Don't use DataAvailable at all. A continuous reading loop is quite straight forward and it is how it's usually done. You can use await if you want. – usr Aug 10 '15 at 10:16