Right way to receive Images over tcp?

Greetings,

I have another application developed in C#, that sends a bunch of images, with diferent sizes (97kb, 123kb, 85kb …).

I have this code that receive the image

    byte[] bytes = new byte[180000];
    if (networkStream.CanRead) // network from the socket TCP 
    {
                  byte[] myReadBuffer = new byte[1024];
                            
                  int numberOfBytesRead = 0;
                          
                     // Incoming message may be larger than the buffer size.
                      do
                      {
                            numberOfBytesRead=networkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
                            myReadBuffer.CopyTo(bytes, numberOfBytesRead);
                                
                      } while (networkStream.DataAvailable);
                           
                         
 }
     Texture2D tx = ByteArrayToImage(bytes); // transform the byte array to image
     Mat.mainTexture = tx; // image goes to the material  texture in a Plane gameObject

But the plane gets just a red interrogation mark as texture, I believe that indicates the texture is corrupted or missing or something like this.

What can I do to get the images right?

Well TCP is just a streaming protocol. All it does is to ensure that no data is lost and that the send data is arrived in the same order as it was send. Note that this doesn’t mean it is received in the same fragmentation that you send it. Just for example if you send 3 strings over TCP:

"Hello "  // 6 bytes
"World"   // 5 bytes
"!"       // 1 byte

then you will most likely receive this:

"Hello World!" // 12 bytes

However it’s also (theoretically) possible that you receive

"He"     // 2 bytes
"llo W"  // 5 bytes
"orl"    // 3 bytes
"d!"     // 2 bytes

In both cases we received all data in the right order. It’s up to you to send the data in a way you can interpret it properly on the other side. That means especially when you want to send multiple seperate chunks of data you need a way to seperate one chunk from the other. So you have to implement your own high level / application level protocol. To avoid getting out of sync for whatever reason it’s recommended to have some sort of starting sequence which marks the beginning of a “chunk” and in addition send a “size” field. So you can construct your own custom “header” which identifies one packet. For example you could set the string "Image" followed by 4 bytes which contain the length of the image data you want to send, followed by the actual image data. That way the receiving side can actually detect the beginning of a chunk and also since we send the size of one chunk in the header we know exactly when one chunk is finished.

The most basic implementation of a simple data chunk protocol would be to just send a 4 byte length header followed by the actual data. That way we know exactly when the data of a chunk of data is done and we can read the next length header.

Note that the code you’ve posted has several additional flaws. First of all you quit your while loop as soon as “DataAvailable” is false. That makes no sense. DataAvailable only indicates that the socket has data available to read. That doesn’t mean that there might not arrive additional data later in time. Next issue is you use two buffers and you copy the conten of your smaller buffer into the larger one. However you don’t track the current position inside the larger buffer. So you always copy the smaller buffer into the first 1024 bytes of the larger buffer. You don’t really need the second buffer as you can specify the offset inside the Read method of the networkstream.

Since you use synchronous read operations it’s highly recommended that you run your receiving code on a seperate thread. There you could simply use the BinaryReader to read the length and the chunk of data. This would make the receiving side quite simple. You should be able to use ReadInt32 to read the size / length and then just use ReadBytes with the length you just read. Just repeat this process for every image you want to receive from the stream. Of course currently we don’t really have a concept for indicating the “end” of our image series (if that is even required). You could send a length of “0” at the end to indicate that no more images will follow and the receiving side can stop reading. Though we don’t know enough about your usecase to give a more detailed description or recommendation.

edit

I created a small example. Here’s a standalone .NET application (pastebin) which serves as TCP server and sends every 500ms a random png images from a folder to all connected clients.

Here’s a MonoBehaviour which acts as client (pastebin) and connects to the above mentioned server, receives the images, load them into a texture and replaces that in a material.

Finally here’s how it looks like in action:

Hi @Fabio_Vieira,
Did you get it working?
The answer of @Bunny83 is quite convincing but still, I am not able to get it.