'C# / Unity - TCP Server with multiple changing clients

I'm trying to setup a TCP Server connected to multiple clients. The clients can change (disconnect, connect again). I'm not very familiar with network programming. So far my code looks like this:

Server:

private void StartReceiveThread()
    {
        ReceiveThread = new Thread(() => ListenForMessages());
        ReceiveThread.IsBackground = true;
        ThreadRunning = true;
        ReceiveThread.Start();
    }


    private void ListenForMessages()
    {
        try
        {
            TcpListener = new TcpListener(IPAddress.Parse(IP), Port);
            TcpListener.Start();
            Debug.Log("TCP Server is listening");
            while (ThreadRunning)
            {
                TcpClient client = TcpListener.AcceptTcpClient();
                int id = ConnectedClients.Count;
                lock (ConnectedClients)
                {
                    ConnectedClients.Add(id, client);
                }

                Thread t = new Thread(HandleClients);
                t.Start(id);
            }
        }
        catch (Exception exception)
        {
            Debug.Log(exception.Message);
        }
    }

    private void HandleClients(object o)
    {
        int id = (int)o;
        TcpClient client;

        lock (ConnectedClients)
        {
            client = ConnectedClients[id];
        }
        while (ThreadRunning)
        {
            NetworkStream stream = client.GetStream();
            byte[] fileSizeBytes = new byte[4];
            int length = stream.Read(fileSizeBytes, 0, 4);

            int dataLength = BitConverter.ToInt32(fileSizeBytes, 0);

            int bytesLeft = dataLength;
            byte[] data = new byte[dataLength];

            int bufferSize = 1024;
            int bytesRead = 0;

            while (bytesLeft > 0)
            {
                int curDataSize = Math.Min(bufferSize, bytesLeft);
                if (client.Available < curDataSize)
                {
                    curDataSize = client.Available;
                }
                length = stream.Read(data, bytesRead, curDataSize);

                bytesRead += curDataSize;
                bytesLeft -= curDataSize;
            }

            if (data.Length > 0)
            {
                lock (IncomingQueue)
                {
                    IncomingQueue.Enqueue(data);
                }
            }
        }
        lock (ConnectedClients)
        {
            ConnectedClients.Remove(id);
        }
    }

    public void Send(byte[] packet)
    {
        if (!ThreadRunning)
        {
            return;
        }
        try
        {
            lock (ConnectedClients)
            {
                foreach (TcpClient client in ConnectedClients.Values)
                {
                    NetworkStream stream = client.GetStream();
                    if (stream.CanWrite)
                    {
                        int bufferSize = 1024;

                        byte[] dataLength = BitConverter.GetBytes(packet.Length);

                        stream.Write(dataLength, 0, 4);

                        int bytesSent = 0;
                        int bytesLeft = packet.Length;

                        while (bytesLeft > 0)
                        {
                            int curDataSize = Math.Min(bufferSize, bytesLeft);
                            stream.Write(packet, bytesSent, curDataSize);

                            bytesSent += curDataSize;
                            bytesLeft -= curDataSize;
                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            Debug.Log(e.Message});
        }
    }

Client:

private void ConnectToServer()
    {
        ReceiveThread = new Thread(new ThreadStart(StartListening));
        ReceiveThread.IsBackground = true;
        ThreadRunning = true;
        ReceiveThread.Start();
    }


    private void StartListening()
    {
        ListenForData();
    }

    private async Task ListenForData()
    {
        while (ThreadRunning)
        {
            TcpClient = new TcpClient();
            if (!TcpClient.Connected)
            {
                try {
                    await TcpClient.ConnectAsync(IPAddress.Parse(IP), Port);
                    ClientConnected = true;
                }
                catch(Exception e)
                {
                    Debug.Log($"Connection failed. Retry in one second.");
                    await Task.Delay(1000);
                }
            }
            if (TcpClient.Connected)
            {
                Debug.Log("connected");
                using (NetworkStream stream = TcpClient.GetStream())
                {
                    byte[] fileSizeBytes = new byte[4];
                    int length = stream.Read(fileSizeBytes, 0, 4);

                    int dataLength = BitConverter.ToInt32(fileSizeBytes, 0);

                    int bytesLeft = dataLength;
                    byte[] data = new byte[dataLength];

                    int bufferSize = 1024;
                    int bytesRead = 0;

                    
                    while (bytesLeft > 0)
                    {
                        int curDataSize = Math.Min(bufferSize, bytesLeft);
                        if (TcpClient.Available < curDataSize)
                        {
                            curDataSize = TcpClient.Available;
                        }
                        length = stream.Read(data, bytesRead, curDataSize);

                        bytesRead += curDataSize;
                        bytesLeft -= curDataSize;
                    }

                    if (data.Length > 0)
                    {
                        lock (IncomingQueue)
                        {
                            IncomingQueue.Enqueue(data);
                        }
                    }
                }
            }
        }
        TcpClient.Client.Shutdown(SocketShutdown.Send);
        TcpClient.Close();
    }

It works with one connected client. But as soon as I disconnect the client and start it again I get the following Message: "Unable to write data to the transport connection: An existing connection was aborted by the host computer."

I searched already a lot and couldn't find a better way so far. Any help would be much appreciated.

Thanks!

[EDIT] The accepted answer in this post was my inspiration for handling multiple clients: C# TCP/IP simple chat



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source