Search code examples
c#.netsocketssynchronous

2 threads handling sockets with weird behaviour


I just finished my C# proxy containing 2 sockets (one client-socket receiving data from a certain client, one server-socket receiving data from a certain server).

- Method I)

The fully working receive/send procedure from a previous early-alpha version uses the following memory eating, quick and dirty method I won't implement again:

            while (true)
            {
                if (ClientSocket.Available > 0)
                {
                    // Received data from the game client
                    byte[] buf = new byte[ClientSocket.Available];
                    ClientSocket.Receive(buf);
                    Packet p = new Packet(buf);
                    Logger.Log(p.ID, LogType.PACKET);
                    // Forward re-encrypted data back to the official server
                    ServerSocket.Send(p.Encrypt());
                }

                if (ServerSocket.Available > 0)
                {
                    // Received Data from the official server
                    byte[] buf = new byte[ServerSocket.Available];
                    ServerSocket.Receive(buf);
                    Packet p = new Packet(buf);
                    Logger.Log(p.ID, LogType.PACKET);
                    // Forward re-encrypted data back to the game client
                    ClientSocket.Send(p.Encrypt());
                }
            }

- Method II)

The not working receive/send procedure from the actual version uses the following memory friendly method split into 2 threads:

class ClientReceiveThread
{
    public Thread T { get; set; }
    public ClientReceiveThread(Socket ClientSocket, Socket ServerSocket)
    {
        T = new Thread(() =>
        {
            try
            {               
                while (ClientSocket.Available > 0)
                {
                    // Received data from the game client
                    byte[] buf = new byte[ClientSocket.Available];
                    ClientSocket.Receive(buf);
                    Packet p = new Packet(buf);
                    Logger.Log(p.ID, LogType.PACKET);
                    // Forward re-encrypted data back to the official server
                    ServerSocket.Send(p.Encrypt());
                }
            }
            catch (Exception e)
            {
                ExceptionHandler.Handle(e);
            }
        });
        T.Start();
    }
}

class ServerReceiveThread
{
    public Thread T { get; set; }
    public ServerReceiveThread(Socket ClientSocket, Socket ServerSocket)
    {
        T = new Thread(() =>
        {
            try
            {
                while (ServerSocket.Available > 0)
                {
                    // Received Data from the official server
                    byte[] buf = new byte[ServerSocket.Available];
                    ServerSocket.Receive(buf);
                    Packet p = new Packet(buf);
                    Logger.Log(p.ID, LogType.PACKET);
                    // Forward re-encrypted data back to the game client
                    ClientSocket.Send(p.Encrypt());
                }
            }
            catch (Exception e)
            {
                ExceptionHandler.Handle(e);
            }
        });
        T.Start();
    }
}

Method I) does insofar work that both Client- and Serversockets receive data, while method II) only receives data from the ClientReceiveThread. Why does ServerReceiveThread in method II) not receive data? It's basically the same code as in the while(true) loop, only ported to a seperate thread.

Any suggestions or answers are highly appreciated. Thanks in advance!


Solution

  • Fixed it by avoiding the "Available" property:

    class ClientReceiveThread
    {
        public Thread T { get; set; }
        public ClientReceiveThread(Socket ClientSocket, Socket ServerSocket)
        {
            T = new Thread(() =>
            {
                try
                {               
                    byte[] buf = new byte[1024];
                    while (ClientSocket.Receive(buf) > 0)
                    {
                        // Received data from the game client
                        Packet p = new Packet(buf);
                        Logger.Log(p.ID, LogType.PACKET);
                        // Forward re-encrypted data back to the official server
                        ServerSocket.Send(p.Encrypt());
                    }
                }
                catch (Exception e)
                {
                    ExceptionHandler.Handle(e);
                }
            });
            T.Start();
        }
    }
    
    class ServerReceiveThread
    {
        public Thread T { get; set; }
        public ServerReceiveThread(Socket ClientSocket, Socket ServerSocket)
        {
            T = new Thread(() =>
            {
                try
                {
                    byte[] buf = new byte[1024];
                    while (ServerSocket.Receive(buf) > 0)
                    {
                        // Received Data from the official server
                        Packet p = new Packet(buf);
                        Logger.Log(p.ID, LogType.PACKET);
                        // Forward re-encrypted data back to the game client
                        ClientSocket.Send(p.Encrypt());
                    }
                }
                catch (Exception e)
                {
                    ExceptionHandler.Handle(e);
                }
            });
            T.Start();
        }
    }