Click here to Skip to main content
15,887,676 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have a multithreaded server-client system where clients chat with the server and receive the sent message back, but only client-to-server way of communication. I want to make it client-to-client. The thing is that I don't know how to distinguish between the clients and perhaps attach each-other's network streams to one-another.

I don't want to make it for 2 clients only, but to make it in a generic way so I can connect i.e. 6 clients, so that every second connected client finds the previous connected one.

I have thought of a TcpClient[] array where I store the clients objects after their connection is accepted, but then I just can't figure out how to distinguish between them and attach them to one-another.

Here is the code of the server class:
C#
class TheServer
{
    private TcpListener tcpListener;
    private Thread threadListener;
    TheMessage msg;
    public TcpClient[] clientList = new TcpClient[100];
    private int n = 0;

    public void StartServer()
    {
        try
        {
            this.tcpListener = new TcpListener(IPAddress.Any, 8000);
            this.threadListener = new Thread(new ThreadStart(ListenForClients));
            this.threadListener.Start();

            Console.WriteLine("Local end point: " + tcpListener.LocalEndpoint);
        }
        catch (Exception e)
        {
            throw;
        }
    }

    private void ListenForClients()
    {
        this.tcpListener.Start();

        while(true)
        {
            // block until a client has connected to the server
            TcpClient client = this.tcpListener.AcceptTcpClient();
            if (n == 0)
            {
                clientList[0] = client;
            }
            else
            {
                n++;
                clientList[n] = client;
            }

            // create thread to handle communication with connected client
            Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
            clientThread.Start(clientList[n]);

        }
    }

    private void HandleClientComm(object client)
    {
        TcpClient tcpClient = (TcpClient)client;
        NetworkStream stm = tcpClient.GetStream();
        msg = new TheMessage();

        while (true)
        {
            Byte[] bSize = new Byte[sizeof(Int32)];
            stm.Read(bSize, 0, bSize.Length);

            Byte[] bData = new Byte[BitConverter.ToInt32(bSize, 0)];
            stm.Read(bData, 0, bData.Length);

            msg = XmlRefactorServer.ByteArrayToObject<TheMessage>(bData);
            String str = msg.Message;
            Console.WriteLine(str);
            stm.Flush();

            // send back to client
            msg.Message = str;
            Byte[] bDataBack = XmlRefactorServer.ObjectToByteArray<TheMessage>(msg);

            // NetworkStream stm2 = ------> perhaps here should get the second client stream ?!

            Byte[] bSizeBack = BitConverter.GetBytes(bDataBack.Length);

            stm2.Write(bSizeBack, 0, bSizeBack.Length);
            stm2.Write(bDataBack, 0, bDataBack.Length);
            stm2.Flush();

        }

        tcpClient.Close();

    }
Posted

1 solution

Just one note:

C#
try
{
    // anything
    // ...
}
catch (Exception e) //   DON'T
{                   //   DO
    throw;          //   SUCH
}                   //   THINGS!


is strictly equivalent to having no exception handling in this fragment, logically, but it just wastes resources. Not having exception handling in this fragment would be the best option. If you are going to write the rest of you code in such a manner, the rest of it presents no interest to me: I would not bet a cent for your project.

Besides, what's the idea: a thread per client (sorry for asking, I want to make sure)? This would be a bad idea, not scalable. The number of threads should not depend on the number of clients.

The question on "client to client" does not make much sense. Let's put it this way: forget client-server model, it's too limiting. Any part of the application can play the role of a server and a client at the same time, in relations to some other parts. However, a TCP channel is asymmetric, it terms of establishing of a connection: one side is a listener and accepts a connection, another part connects. When a connection is established, both parts can read and write to a socket, according to some application-level protocol you can devise. Start from this point. I don't want to give you further recommendation, because I don't know what kind of communication scenario do you have in mind.

—SA
 
Share this answer
 
v3

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