Hashim Roja
Hashim Roja

Reputation: 65

Async socket server with multiple clients

i have a problem i am unable to resolve as my c# knowledge is not very good. I found some code on the internet and modified it according to my needs.

My problem is that when i send messages to clients only one receives the message, then the next message is received by another client and so on. I want to send same message to all connected clients without losing any data.

Server

using System;
using System.Net.Sockets;
using System.Threading;


public class AsynchIOServer
{
    static TcpListener tcpListener = new TcpListener(10);

    static void Listeners()
    {

        Socket socketForClient = tcpListener.AcceptSocket();
        if (socketForClient.Connected)
        {
            Console.WriteLine("Client:"+socketForClient.RemoteEndPoint+" now connected to server.");
            NetworkStream networkStream = new NetworkStream(socketForClient);
            System.IO.StreamWriter streamWriter =
            new System.IO.StreamWriter(networkStream);
            System.IO.StreamReader streamReader =
            new System.IO.StreamReader(networkStream);

            ////here we send message to client
            while (true){
                Console.WriteLine("type your message to be recieved by client:");
                string theString = Console.ReadLine();
                streamWriter.WriteLine(theString);
                ////Console.WriteLine(theString);
                streamWriter.Flush();
            }
            streamReader.Close();
            networkStream.Close();
            streamWriter.Close();

        }
        socketForClient.Close();
        Console.WriteLine("Press any key to exit from server program");
        Console.ReadKey();
    }

    public static void Main()
    {
        //TcpListener tcpListener = new TcpListener(10);
        tcpListener.Start();
        Console.WriteLine("************This is Server program************");
        Console.WriteLine("Hoe many clients are going to connect to this server?:");
        int numberOfClientsYouNeedToConnect =int.Parse( Console.ReadLine());
        for (int i = 0; i < numberOfClientsYouNeedToConnect; i++)
        {
            Thread newThread = new Thread(new ThreadStart(Listeners));
            newThread.Start();
        }
    }
}

Client:

using System;
using System.Net.Sockets;
using System.Threading;
public class Client
{
    static public void Main(string[] Args)
    {
        TcpClient socketForServer;
        try
        {
            socketForServer = new TcpClient("localHost", 10);
        }
        catch
        {
            Console.WriteLine(
            "Failed to connect to server at {0}:999", "localhost");
            return;
        }

        NetworkStream networkStream = socketForServer.GetStream();
        System.IO.StreamReader streamReader =
        new System.IO.StreamReader(networkStream);
        System.IO.StreamWriter streamWriter =
        new System.IO.StreamWriter(networkStream);
        Console.WriteLine("*******This is client program who is connected to localhost on port No:10*****");

            try
            {
                string outputString;
            // read the data from the host and display it
            {
                while (true)
                {
                    outputString = streamReader.ReadLine();
                    Console.WriteLine("Message Recieved by server:" + outputString);

                    streamWriter.Flush();
                }
            }
        }
            catch
            {
                Console.WriteLine("Exception reading from Server");
            }
        // tidy up
        networkStream.Close();
        Console.WriteLine("Press any key to exit from client program");
        Console.ReadKey();
    }

    private static string GetData()
    {
        //Ack from sql server
        return "ack";
    }
}

Thank you

Upvotes: 2

Views: 6072

Answers (2)

Lucca Ferri
Lucca Ferri

Reputation: 1347

Your code is wrong.

First of all I'll give you some insight of how it's wrong and why it's not working the way you want.

You're creating n number of threads, and making them ALL wait for a connection. What if you exhaust the number of threads? What if any of them exits unexpectedly?

You are also sending the data wrong. By using Console.ReadLine you aren't passing the data through multiple threads and reading the line in each one, instead, the first one that calls Console.ReadLine will be the one that's going to receive it. This means you'll only be sending to only one Socket.

It's not ideal how you're managing this. There are dozens if not hundreds of multithreaded socket server/client available online, and I'd invite you to research a little bit more. But first I'd like you to research more about Thread/Task in C#.

Upvotes: 1

D .Stark
D .Stark

Reputation: 89

simple working multi-threaded server:

    static void Process(Socket client) {

        Console.WriteLine("Incoming connection from " + client.RemoteEndPoint);

        const int maxMessageSize = 1024;
        byte[] response;
        int received;

        while (true) {

            // Send message to the client:
            Console.Write("Server: ");
            client.Send(Encoding.ASCII.GetBytes(Console.ReadLine()));
            Console.WriteLine();

            // Receive message from the server:
            response = new byte[maxMessageSize];
            received = client.Receive(response);
            if (received == 0) {
                Console.WriteLine("Client closed connection!");
                return;
            }

            List<byte> respBytesList = new List<byte>(response);
            respBytesList.RemoveRange(received, maxMessageSize - received); // truncate zero end
            Console.WriteLine("Client (" + client.RemoteEndPoint + "+: " + Encoding.ASCII.GetString(respBytesList.ToArray()));
        }
    }

    static void Main(string[] args) {

        int backlog = -1, port = 2222;

        Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        server.ReceiveTimeout = -1;

        // Start listening.
        try {
            server.Bind(new IPEndPoint(IPAddress.Any, port));
            server.Listen(backlog);
        }
        catch (Exception) {
            Console.WriteLine("Listening failed!");
            Console.ReadKey();
            return;
        }

        Console.WriteLine("Start listening...");

        while(true) {
            Socket client = server.Accept();
            new System.Threading.Thread(() => {
                try { Process(client); } catch (Exception ex) { Console.WriteLine("Client connection processing error: " + ex.Message); }
            }).Start();
        }

        //Console.WriteLine("Press any key for exit...");
        //Console.ReadKey();
    }

And client:

    static void WorkWithServer(Socket server) {

        const int maxMessageSize = 1024;
        byte[] response;
        int received;

        while(true) {

            try {

                // Receive message from the server:
                response = new byte[maxMessageSize];
                received = server.Receive(response);
                if (received == 0) {
                    Console.WriteLine("Server closed connection.");
                    return;
                }

                List<byte> respBytesList = new List<byte>(response);
                respBytesList.RemoveRange(received, maxMessageSize - received); // truncate zero end
                Console.WriteLine("Server: " + Encoding.ASCII.GetString(respBytesList.ToArray()));

                // Send message to the server:
                Console.Write("You: ");
                server.Send(Encoding.ASCII.GetBytes(Console.ReadLine()));
                Console.WriteLine();
            }
            catch (Exception ex) {
                Console.WriteLine("Error: " + ex.Message);
                return;
            }
        }

    }

    static void Main(string[] args) {

        IPEndPoint serverEp = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 2222);

        Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        server.ReceiveTimeout = -1;

        // Connect to the server.
        try { server.Connect(serverEp); }
        catch (Exception) {
            Console.WriteLine("Establish connection with server (" + serverEp + ") failed!");
            Console.ReadKey();
            return;
        }

        Console.WriteLine("Connection with server (" + serverEp + ") established!");
        WorkWithServer(server);

        Console.WriteLine("Press any key for exit...");
        Console.ReadKey();
    }

Edit as you need.

Upvotes: 1

Related Questions