title: unity - Transfer image from server to clients using tcp sockets. Need help in code alterations
body: <p>Below is the code which i am working on. I got this code from this link :<a href="https://stackoverflow.com/questions/42717713/unity-live-video-streaming">video streaming link</a>. I have modified this code to transfer image files, whenever i click a send button in Unity. The images got transferred form the server to client as expected.
  The problem I face is as follows:</p>
  
  <ul>
  <li>whenever i close the client app and reopen, number of connected clients shows incremented.</li>
  <li>not sure how to send images to more number of clients</li>
  <li>when the server app is closed and  opened, the conection is not established/ image not transferring.</li>
  <li>Also help how i can improve the code better. Thank you.</li>
  </ul>
  
  <p>Server Code:</p>
  
  
  
  <pre class="lang-c# prettyprint-override"><code>using UnityEngine;
  using System.Collections;
  using System.IO;
  using UnityEngine.UI;
  using System;
  using System.Text;
  using System.Net;
  using System.Net.Sockets;
  using System.Threading;
  using System.Collections.Generic;
  
  public class ServerScript : MonoBehaviour
  {
      public RawImage myImage;
      public bool enableLog = false;
      public Text logtext;
  
      Texture2D currentTexture;
      private TcpListener listner;
      private const int port = 7777;
      private bool stop = false;
  
      bool isConnected = false;
      TcpClient client = null;
      NetworkStream stream = null;
  
      private List&lt;TcpClient&gt; clients = new List&lt;TcpClient&gt;();
  
      //This must be the-same with SEND_COUNT on the client
      const int SEND_RECEIVE_COUNT = 15;
  
      private void Start()
      {
          Application.runInBackground = true;
          currentTexture = new Texture2D(300, 300);
  
          // Connect to the server
          listner = new TcpListener(IPAddress.Any, port);
  
          listner.Start();
  
          // Wait for client to connect in another Thread 
          Loom.RunAsync(() =&gt;
              {
                  while (!stop)
                  {
                      // Wait for client connection
                      client = listner.AcceptTcpClient();
                      // We are connected
                      clients.Add(client);
  
                      isConnected = true;
                      stream = client.GetStream();
                  }
              });
  
      }
  
      //send an image when the button is clicked
      public void sendButton(){
          //Start sending coroutine
          logtext.text = "Notsentimage";
          stop = false;
          StartCoroutine(senderCOR());
      }
  
      void OnGUI(){
          string ipaddress = Network.player.ipAddress;
          GUI.Box (new Rect (10, Screen.height - 50, 100, 50), ipaddress);
          GUI.Label (new Rect (20, Screen.height - 35, 100, 20), "Status" );
          GUI.Label (new Rect (20, Screen.height - 20, 100, 20), "Connected" + clients.Count);
      }
  
      //Converts the data size to byte array and put result to the fullBytes array
      void byteLengthToFrameByteArray(int byteLength, byte[] fullBytes)
      {
          //Clear old data
          Array.Clear(fullBytes, 0, fullBytes.Length);
          //Convert int to bytes
          byte[] bytesToSendCount = BitConverter.GetBytes(byteLength);
          //Copy result to fullBytes
          bytesToSendCount.CopyTo(fullBytes, 0);
      }
  
      //Converts the byte array to the data size and returns the result
      int frameByteArrayToByteLength(byte[] frameBytesLength)
      {
          int byteLength = BitConverter.ToInt32(frameBytesLength, 0);
          return byteLength;
      }
  
      IEnumerator senderCOR()
      {
  
          //Wait until client has connected
          while (!isConnected)
          {
              yield return null;
          }
  
          LOG("Connected!");
  
          bool readyToGetFrame = true;
  
          byte[] frameBytesLength = new byte[SEND_RECEIVE_COUNT];
  
          while (!stop)
          {
              currentTexture = myImage.texture as Texture2D;
              byte[] pngBytes = currentTexture.EncodeToPNG();
              //Fill total byte length to send. Result is stored in frameBytesLength
              byteLengthToFrameByteArray(pngBytes.Length, frameBytesLength);
  
              //Set readyToGetFrame false
              readyToGetFrame = false;
  
              Loom.RunAsync(() =&gt;
                  {
                      //Send total byte count first
                      stream.Write(frameBytesLength, 0, frameBytesLength.Length);
                      LOG("Sent Image byte Length: " + frameBytesLength.Length);
  
                      //Send the image bytes
                      stream.Write(pngBytes, 0, pngBytes.Length);
                      LOG("Sending Image byte array data : " + pngBytes.Length);
                      //logtext.text = "sentimage";
  
                      //Sent. Set readyToGetFrame true
                      readyToGetFrame = true;
                  });
  
              //Wait until we are ready to get new frame(Until we are done sending data)
              while (!readyToGetFrame)
              {logtext.text = "sentimage";
                  LOG("Waiting To get new frame");
                  yield return null;
              }
              stop = true;
          }
  
      }
  
  
      void LOG(string messsage)
      {
          if (enableLog)
              Debug.Log(messsage);
  
      }
  
      private void Update()
      {
  
      }
  
      // stop everything
      public void OnApplicationQuit()
      {
          if (listner != null)
          {
              listner.Stop();
          }
  
          foreach (TcpClient c in clients)
              c.Close();
      }
  }
  </code></pre>
  
  <p>Client Code:</p>
  
  <pre class="lang-c# prettyprint-override"><code>using UnityEngine;
  using System.Collections;
  using UnityEngine.UI;
  using System.Net.Sockets;
  using System.Net;
  using System.IO;
  using System;
  
  public class ClientScript : MonoBehaviour
  {
      public RawImage image;
      //public InputField Ipinput;
      public Text Ipinput;
      public Text logtext;
      public Text infotext;
      public bool enableLog = true;
      bool disconnected = false;
  
      const int port = 7777;
      //public string IP = "192.168.0.101";
      TcpClient client;
  
      Texture2D tex;
  
      private bool stop = false;
  
      //This must be the-same with SEND_COUNT on the server
      const int SEND_RECEIVE_COUNT = 15;
  
      // Use this for initialization
      void Start()
      {
          Application.runInBackground = true;
  
          tex = new Texture2D(0, 0);
          client = new TcpClient();
  
          //Connect to server from another Thread
          Loom.RunAsync(() =&gt;
              {
                  LOGWARNING("Connecting to server...");
                  // if on desktop
                  client.Connect("192.168.0.102", port);
  
                  // if using the IPAD
                  //client.Connect(IPAddress.Parse(IP), port);
                  LOGWARNING("Connected!");
  
                  imageReceiver();
              });
      }
  
      void OnGUI(){
  
          string ipaddress = Network.player.ipAddress;
          GUI.Box (new Rect (10, Screen.height - 50, 100, 50), ipaddress);
          GUI.Label (new Rect (20, Screen.height - 30, 100, 20), "Status "+ client.Connected);
      }
  
      void imageReceiver()
      {
          //While loop in another Thread is fine so we don't block main Unity Thread
          Loom.RunAsync(() =&gt;
              {
                  while (!stop)
                  {
                      //Read Image Count
                      int imageSize = readImageByteSize(SEND_RECEIVE_COUNT);
                      LOGWARNING("Received Image byte Length: " + imageSize);
  
                      //Read Image Bytes and Display it
                      readFrameByteArray(imageSize);
                  }
              });
      }
  
  
      //Converts the data size to byte array and put result to the fullBytes array
      void byteLengthToFrameByteArray(int byteLength, byte[] fullBytes)
      {
          //Clear old data
          Array.Clear(fullBytes, 0, fullBytes.Length);
          //Convert int to bytes
          byte[] bytesToSendCount = BitConverter.GetBytes(byteLength);
          //Copy result to fullBytes
          bytesToSendCount.CopyTo(fullBytes, 0);
      }
  
      //Converts the byte array to the data size and returns the result
      int frameByteArrayToByteLength(byte[] frameBytesLength)
      {
          int byteLength = BitConverter.ToInt32(frameBytesLength, 0);
          return byteLength;
      }
  
  
      /////////////////////////////////////////////////////Read Image SIZE from Server///////////////////////////////////////////////////
      private int readImageByteSize(int size)
      {
          disconnected = false;
  
          NetworkStream serverStream = client.GetStream();
          byte[] imageBytesCount = new byte[size];
          var total = 0;
          do
          {
              var read = serverStream.Read(imageBytesCount, total, size - total);
              //Debug.LogFormat("Client recieved {0} bytes", total);
              if (read == 0)
              {
                  disconnected = true;
                  infotext.text = "disconnected";
                  break;
              }
              total += read;
          } while (total != size);
  
          int byteLength;
  
          if (disconnected)
          {
              byteLength = -1;
          }
          else
          {   infotext.text = "connected";
              byteLength = frameByteArrayToByteLength(imageBytesCount);
          }
          return byteLength;
      }
  
      /////////////////////////////////////////////////////Read Image Data Byte Array from Server///////////////////////////////////////////////////
      private void readFrameByteArray(int size)
      {
          bool disconnected = false;
  
          NetworkStream serverStream = client.GetStream();
          byte[] imageBytes = new byte[size];
          var total = 0;
          do
          {
              var read = serverStream.Read(imageBytes, total, size - total);
              //Debug.LogFormat("Client recieved {0} bytes", total);
              if (read == 0)
              {
                  disconnected = true;
                  infotext.text = "disconnected";
                  break;
              }
              total += read;
          } while (total != size);
  
          bool readyToReadAgain = false;
  
          //Display Image
          if (!disconnected)
          {
              infotext.text = "connected";
              //Display Image on the main Thread
              Loom.QueueOnMainThread(() =&gt;
                  {
                      displayReceivedImage(imageBytes);
                      readyToReadAgain = true;
                  });
          }
  
          //Wait until old Image is displayed
          while (!readyToReadAgain)
          {
              System.Threading.Thread.Sleep(1);
          }
  
          //stop = true;
      }
  
  
      void displayReceivedImage(byte[] receivedImageBytes)
      {
          tex.LoadImage(receivedImageBytes);
          image.texture = tex;
      }
  
  
      // Update is called once per frame
      void Update()
      {
          if (disconnected){
          Loom.RunAsync(() =&gt;
              {
                  client.Connect("192.168.0.102", port);
                      disconnected = false;               
                  });
          }
      }
  
  
      void LOG(string messsage)
      {
          if (enableLog)
              Debug.Log(messsage);
      }
  
      void LOGWARNING(string messsage)
      {
          if (enableLog)
              logtext.text = messsage;
      }
  
      public void OnApplicationQuit()
      {
          LOGWARNING("OnApplicationQuit");
          stop = true;
  
          if (client != null)
          {
              client.Close();
          }
      }
  }
  </code></pre>