Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#
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:
 

    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 3-Feb-13 9:17am
Yvar Birx2.4K
Comments
Sergey Alexandrovich Kryukov at 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 at 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 at 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 at 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

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

After Client.Close, add Client.Dispose
After tcpClient.Close, add tcpClient.Dispose
 
See TcpClient.Dispose Method [^]
  Permalink  

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

  Print Answers RSS
0 OriginalGriff 645
1 Maciej Los 225
2 Abhinav S 171
3 Richard Deeming 160
4 Suvendu Shekhar Giri 159
0 Sergey Alexandrovich Kryukov 9,623
1 OriginalGriff 9,135
2 Peter Leow 5,042
3 Kornfeld Eliyahu Peter 3,373
4 Maciej Los 2,581


Advertise | Privacy | Mobile
Web04 | 2.8.150327.1 | Last Updated 3 Feb 2013
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100