This is a sample tutorial on how to create a TCP server that can handle multiple clients at the same time.
What you need to have is a server that listen to a port from your computer(server) and whenever a client connects, it starts a thread that handles the communication with that particular client.
The Client Class.
class ClientDemo
{
private TcpClient _client;
private StreamReader _sReader;
private StreamWriter _sWriter;
private Boolean _isConnected;
public ClientDemo(String ipAddress, int portNum)
{
_client = new TcpClient();
_client.Connect(ipAddress, portNum);
HandleCommunication();
}
public void HandleCommunication()
{
_sReader = new StreamReader(_client.GetStream(), Encoding.ASCII);
_sWriter = new StreamWriter(_client.GetStream(), Encoding.ASCII);
_isConnected = true;
String sData = null;
while (_isConnected)
{
Console.Write("> ");
sData = Console.ReadLine();
// write data and make sure to flush, or the buffer will continue to
// grow, and your data might not be sent when you want it, and will
// only be sent once the buffer is filled.
_sWriter.WriteLine(sData);
_sWriter.Flush();
// if you want to receive anything
// String sDataIncomming = _sReader.ReadLine();
}
}
}
In this class we’re going to need to a instantiate a TcpClient so we can have a connection with the server.
To handle communication to and from the server, a StreamReader and StreamWriter are used so we can easily write and read data. We could use a NetworkStream but you can’t force flush so I find it better to use the StreamReader/Writer.
To instantiate them you just have to feed them the stream from the client’s connection.
After that, I just ask for input and send it to the server. From there you can do anything you want. Process the data you receive from the server to close the client or do other fun stuff.
The Server Class
class TcpServer
{
private TcpListener _server;
private Boolean _isRunning;
public TcpServer(int port)
{
_server = new TcpListener(IPAddress.Any, port);
_server.Start();
_isRunning = true;
LoopClients();
}
public void LoopClients()
{
while (_isRunning)
{
// wait for client connection
TcpClient newClient = _server.AcceptTcpClient();
// client found.
// create a thread to handle communication
Thread t = new Thread(new ParameterizedThreadStart(HandleClient));
t.Start(newClient);
}
}
public void HandleClient(object obj)
{
// retrieve client from parameter passed to thread
TcpClient client = (TcpClient)obj;
// sets two streams
StreamWriter sWriter = new StreamWriter(client.GetStream(), Encoding.ASCII);
StreamReader sReader = new StreamReader(client.GetStream(), Encoding.ASCII);
// you could use the NetworkStream to read and write,
// but there is no forcing flush, even when requested
Boolean bClientConnected = true;
String sData = null;
while (bClientConnected)
{
// reads from stream
sData = sReader.ReadLine();
// shows content on the console.
Console.WriteLine("Client > " + sData);
// to write something back.
// sWriter.WriteLine("Meaningfull things here");
// sWriter.Flush();
}
}
}
In this class, you’ll have to have a TcpListener Class. When you start your Server class, you’ll be opening a port on the machine and will be waiting for clients to connect.
Once a client connects, a thread is fired and the client who got connected is passed to the thread as a parameter, so we don’t loose the connection.
The thread starts a function that will handle communication with clients. First, we recover the client from the object passed in the thread as parameter. Then we create our streams to write and read from the client’s stream. Each client has a two private streams, that is why they are created inside HandleClient(object obj) method, so they don’t share the same streams.
After that, you can do what you want, send and receive data
Client Main Class
namespace Client
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Multi-Threaded TCP Server Demo");
Console.WriteLine("Provide IP:");
String ip = Console.ReadLine();
Console.WriteLine("Provide Port:");
int port = Int32.Parse(Console.ReadLine());
ClientDemo client = new ClientDemo(ip, port);
}
}
}
Server Main Class
namespace Multi_Threaded_TCP
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Multi-Threaded TCP Server Demo");
TcpServer server = new TcpServer(5555);
}
}
}
Note: Just change the “5555″ to whatever you want. That’s the port the server will be listening to. Or even better, ask for it when launching the application or store it in a configuration file.
You can download the project sample here.
Multi_Threaded_TCP