Click here to Skip to main content
15,881,559 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello codeproject,

I am currently attempting to create a threaded TCP client and server. And I am wondering if anyone has any suggestions or improvements for this, as I am not so experienced in handling socket connections. Here is my attempt:


C#
public class Server
{
    #region -- Variables
    private TcpListener tcpListener;
    private Thread listenThread;

    public List<TcpClient> Connections = new List<TcpClient>();
    #endregion

    public Server(int Port)
    {
        // - Create the variables.
        this.tcpListener = new TcpListener(IPAddress.Any, Port);
        this.listenThread = new Thread(new ThreadStart(SearchClient));

        // -- Start the Thread.
        this.listenThread.Start();
    }

    public void SearchClient()
    {
        // -- Start the Listener.
        this.tcpListener.Start();

        // -- Loop.
        while (true)
        {
            // -- Blocks until there is an incoming connection.
            try
            {
                TcpClient Client = this.tcpListener.AcceptTcpClient();

                // -- Create a new Thread to handle the connection.
                Thread ClientThread = new Thread(new ParameterizedThreadStart(HandleClient));

                // -- Start the Thread.
                ClientThread.Start(Client);
            }
            catch { break; }
        }
    }

    public void HandleClient(object Client)
    {
        // -- Client.
        TcpClient TcpClient = (TcpClient)Client;

        // -- Add the client to the list.
        Connections.Add(TcpClient);

        // -- Stream.
        NetworkStream ClientStream = TcpClient.GetStream();

        // -- Buffer.
        byte[] Buffer = new byte[4096];

        // -- To-use later.
        int bytesRead;

        // -- Loop until asked to stop.
        while (true)
        {

            // -- Initialize the integer.
            bytesRead = 0;

            // -- Attempt to read.
            try
            {
                // -- Blocks until the client sends a message.
                bytesRead = ClientStream.Read(Buffer, 0, Buffer.Length);
            }
            catch { break; /* Socket Exception*/ }

            // -- Did the client disconnect?
            if (bytesRead == 0)
            {
                break;
            }

            // -- Handle buffer here.
        }

        // -- Close the client.
        TcpClient.Close();

        // -- Remove the client from the list.
        Connections.Remove(TcpClient);

    }

    public void SendBuffer(TcpClient TcpClient, byte[] Buffer)
    {
        TcpClient.GetStream().Write(Buffer, 0, Buffer.Length);
    }

    public void StopServer()
    {
        foreach (TcpClient Client in Connections)
        {
            // -- Close the client.
            Client.Close();

        }
        tcpListener.Stop();
    }
}
public class Client
{
    #region -- Variables
    private TcpClient tcpClient;
    private Thread listenThread;

    public bool GotConnection { get; private set; }
    public bool AllowedRead { get; set; }

    private string _IP;
    private int _Port;
    #endregion

    public Client(string IP, int Port)
    {
        // -- Set the variables.
        _IP = IP;
        _Port = Port;


        // - Create the variables.
        this.tcpClient = new TcpClient();
        this.listenThread = new Thread(new ThreadStart(HandleServer));

        // -- Start the Thread.
        this.listenThread.Start();
    }

    public void HandleServer()
    {
        // -- Stream.
        NetworkStream ClientStream = tcpClient.GetStream();

        // -- Buffer.
        byte[] Buffer = new byte[4096];

        // -- To-use later.
        int bytesRead;

        // -- Connection.
        GotConnection = true;

        // -- Loop until asked to stop.
        while (true)
        {
            // -- Allowed Read.
            if (!AllowedRead)
                break;

            // -- Initialize the integer.
            bytesRead = 0;

            // -- Attempt to read.
            try
            {
                // -- Blocks until the client sends a message.
                bytesRead = ClientStream.Read(Buffer, 0, Buffer.Length);
            }
            catch { break; /* Socket Exception*/ }

            // -- Did the client disconnect?
            if (bytesRead == 0)
            {
                break;
            }

            // -- Handle buffer here.
        }

        // -- Connection.
        GotConnection = false;

        // -- Close the client.
        tcpClient.Close();
    }

    public void SendBuffer(byte[] Buffer)
    {
        if (GotConnection)
            tcpClient.GetStream().Write(Buffer, 0, Buffer.Length);
    }

    public void StopClient()
    {
        if (tcpClient.Connected)
            tcpClient.GetStream().Close();
        tcpClient.Close();
        AllowedRead = false;
    }
}
Posted
Comments
Sergey Alexandrovich Kryukov 3-Feb-13 14:31pm    
Well, that is a code dump. To read it, you should better explain why anyone should read it. What are the problems you have with it?
—SA
Matthew Faithfull 3-Feb-13 14:35pm    
Assuming that your posted code works can it be improved? Yes because there's no such thing as perfect code. How to improve it depends on what your goal/specification is. Do you want to improve readability of the source code or the memory usage of the program at runtime? Do you want to increase the number of clients that can be handled or focus on the maximum bits per second throughput of the overall system? There are a lot of ways code can be made better but the basic steps are the same. Find out how good already is by comparing it with an alternative and or measuring/profiling it according to the what you are trying to achieve. Research alternatives to each of the choices you made in the development from which language to use to using or not using threading or a thread pool. If the evidence or collective wisdom says you made the wrong choice then change it and redesign/reimplement. You can of course go on doing this until you run out of time, money or motivation or you achieve perfect code :-)
Yvar Birx 3-Feb-13 15:33pm    
Hello Matthew!
Thanks for your interesting reply. Well basically, I am trying to get it to dispose the TCP Client, because the Tcp Client is always there in the Ram even when I "disposes" or "closed" it. I'm trying it to handle the clients good enough for Windows not to complain that it still exists.
;3
Matthew Faithfull 3-Feb-13 15:49pm    
Ahh, it works as far as the machine is concerned but not enough for humans. I hate those problems and I'm afraid my C# knowledge is not up such a challenge as persuading the runtime to let go of objects that are no longer required. The good news is that there are lots of experts around here who do know that sort of thing. I'd post a very specific question about disposing connected socket objects to the C# forum and check the online .NET docs as well. Other people will have hit the same issue. Sorry I can't be of more help.

1 solution

After Client.Close, add Client.Dispose
After tcpClient.Close, add tcpClient.Dispose

See TcpClient.Dispose Method [^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900