2

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

2
  • What kind of advice are you looking for? The program has some fundamental issues (the program needs one "input" loop, not one per thread) but solving this requires fully understanding what's going on. Commented Sep 21, 2017 at 14:53
  • @C.Evenhuis i know the program is messy, all i want to do is send a message to all the clients Commented Sep 21, 2017 at 15:01

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

thank you for the code, i tested it and it's working but how do i send same message to all the clients at a time the code you gave me sends it to only one person then the next message get's send to the other
You want to enter some text once, so that it is sent to all connected users and then the responses are displayed from each one?
Yes. One text sent to all users at once
Not good in the text input logic, but as a demo version it will suit)
1

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#.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.