Click here to Skip to main content
15,894,825 members
Articles / Programming Languages / C#

A TCP/IP Server written in C#

Rate me:
Please Sign up or sign in to vote.
4.64/5 (62 votes)
29 Dec 2003CPOL8 min read 565K   59.4K   225  
TCP/IP Server, which is running as a Windows Service waiting for client requests
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
using System.IO;

namespace TCPService
{
	/// <summary>
	/// TCPServer is the Server class. When "StartServer" method is called
	/// this Server object tries to connect to a IP Address specified on a port
	/// configured. Then the server start listening for client socket requests.
	/// As soon as a requestcomes in from any client then a Client Socket 
	/// Listening thread will be started. That thread is responsible for client
	/// communication.
	/// </summary>
	public class TCPServer
	{
		/// <summary>
		/// Default Constants.
		/// </summary>
		public static IPAddress DEFAULT_SERVER = IPAddress.Parse("127.0.0.1"); 
		public static int DEFAULT_PORT=31001;
		public static IPEndPoint DEFAULT_IP_END_POINT = 
			new IPEndPoint(DEFAULT_SERVER, DEFAULT_PORT);

		/// <summary>
		/// Local Variables Declaration.
		/// </summary>
		private TcpListener m_server = null;
		private bool m_stopServer=false;
		private bool m_stopPurging=false;
		private Thread m_serverThread = null;
		private Thread m_purgingThread = null;
		private ArrayList m_socketListenersList = null;
		/// <summary>
		/// Constructors.
		/// </summary>
		public TCPServer()
		{
			Init(DEFAULT_IP_END_POINT);
		}
		public TCPServer(IPAddress serverIP)
		{
			Init(new IPEndPoint(serverIP, DEFAULT_PORT));
		}

		public TCPServer(int port)
		{
			Init(new IPEndPoint(DEFAULT_SERVER, port));
		}

		public TCPServer(IPAddress serverIP, int port)
		{
			Init(new IPEndPoint(serverIP, port));
		}

		public TCPServer(IPEndPoint ipNport)
		{
			Init(ipNport);
		}

		/// <summary>
		/// Destructor.
		/// </summary>
		~TCPServer()
		{
			StopServer();
		}

		/// <summary>
		/// Init method that create a server (TCP Listener) Object based on the
		/// IP Address and Port information that is passed in.
		/// </summary>
		/// <param name="ipNport"></param>
		private void Init(IPEndPoint ipNport)
		{
			try
			{
				m_server = new TcpListener(ipNport);
				// Create a directory for storing client sent files.
				if (!Directory.Exists(TCPSocketListener.DEFAULT_FILE_STORE_LOC))
				{
					Directory.CreateDirectory(
						TCPSocketListener.DEFAULT_FILE_STORE_LOC);
				}
			}
			catch(Exception e)
			{
				m_server=null;
			}
		}

		/// <summary>
		/// Method that starts TCP/IP Server.
		/// </summary>
		public void StartServer()
		{
			if (m_server!=null)
			{
				// Create a ArrayList for storing SocketListeners before
				// starting the server.
				m_socketListenersList = new ArrayList();

				// Start the Server and start the thread to listen client 
				// requests.
				m_server.Start();
				m_serverThread = new Thread(new ThreadStart(ServerThreadStart));
				m_serverThread.Start();

				// Create a low priority thread that checks and deletes client
				// SocktConnection objcts that are marked for deletion.
				m_purgingThread = new Thread(new ThreadStart(PurgingThreadStart));
				m_purgingThread.Priority=ThreadPriority.Lowest;
				m_purgingThread.Start();
			}
		}

		/// <summary>
		/// Method that stops the TCP/IP Server.
		/// </summary>
		public void StopServer()
		{
			if (m_server!=null)
			{
				// It is important to Stop the server first before doing
				// any cleanup. If not so, clients might being added as
				// server is running, but supporting data structures
				// (such as m_socketListenersList) are cleared. This might
				// cause exceptions.

				// Stop the TCP/IP Server.
				m_stopServer=true;
				m_server.Stop();

				// Wait for one second for the the thread to stop.
				m_serverThread.Join(1000);
				
				// If still alive; Get rid of the thread.
				if (m_serverThread.IsAlive)
				{
					m_serverThread.Abort();
				}
				m_serverThread=null;
				
				m_stopPurging=true;
				m_purgingThread.Join(1000);
				if (m_purgingThread.IsAlive)
				{
					m_purgingThread.Abort();
				}
				m_purgingThread=null;

				// Free Server Object.
				m_server = null;

				// Stop All clients.
				StopAllSocketListers();
			}
		}


		/// <summary>
		/// Method that stops all clients and clears the list.
		/// </summary>
		private void StopAllSocketListers()
		{
			foreach (TCPSocketListener socketListener 
						 in m_socketListenersList)
			{
				socketListener.StopSocketListener();
			}
			// Remove all elements from the list.
			m_socketListenersList.Clear();
			m_socketListenersList=null;
		}

		/// <summary>
		/// TCP/IP Server Thread that is listening for clients.
		/// </summary>
		private void ServerThreadStart()
		{
			// Client Socket variable;
			Socket clientSocket = null;
			TCPSocketListener socketListener = null;
			while(!m_stopServer)
			{
				try
				{
					// Wait for any client requests and if there is any 
					// request from any client accept it (Wait indefinitely).
					clientSocket = m_server.AcceptSocket();

					// Create a SocketListener object for the client.
					socketListener = new TCPSocketListener(clientSocket);

					// Add the socket listener to an array list in a thread 
					// safe fashon.
					//Monitor.Enter(m_socketListenersList);
					lock(m_socketListenersList)
					{
						m_socketListenersList.Add(socketListener);
					}
					//Monitor.Exit(m_socketListenersList);

					// Start a communicating with the client in a different
					// thread.
					socketListener.StartSocketListener();
				}
				catch (SocketException se)
				{
					m_stopServer = true;
				}
			}
		}

		/// <summary>
		/// Thread method for purging Client Listeneres that are marked for
		/// deletion (i.e. clients with socket connection closed). This thead
		/// is a low priority thread and sleeps for 10 seconds and then check
		/// for any client SocketConnection obects which are obselete and 
		/// marked for deletion.
		/// </summary>
		private void PurgingThreadStart()
		{
			while (!m_stopPurging)
			{
				ArrayList deleteList = new ArrayList();

				// Check for any clients SocketListeners that are to be
				// deleted and put them in a separate list in a thread sage
				// fashon.
				//Monitor.Enter(m_socketListenersList);
				lock(m_socketListenersList)
				{
					foreach (TCPSocketListener socketListener 
								 in m_socketListenersList)
					{
						if (socketListener.IsMarkedForDeletion())
						{
							deleteList.Add(socketListener);
							socketListener.StopSocketListener();
						}
					}

					// Delete all the client SocketConnection ojects which are
					// in marked for deletion and are in the delete list.
					for(int i=0; i<deleteList.Count;++i)
					{
						m_socketListenersList.Remove(deleteList[i]);
					}
				}
				//Monitor.Exit(m_socketListenersList);

				deleteList=null;
				Thread.Sleep(10000);
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions