简体   繁体   中英

C# TCP Server to Multi Clients (Unknown number of clients listening)

I'm trying to write a small program that is built from a Server and some Clients. the Server will transfer / push a Text Message to the clients (the client not allowed to send back to the server, all of the clients should get the same Text Message from the server) I've seen some question about this subject around here and over the net but did not get the exact solution I'm looking for. most of the solutions were to create a thread for each client. but lets assume that I don't always know how many clients will be listening on a certain time. could be 2 and could be 30. I know there's a way of making a Thread pool and let .NET deal with assigning the threads but never had a good practice with that nor my knowledge with Threading is any good. for now I have a simple Sever to Client program that works as expected but again, only with one client. so here is my code:

Server:

using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows;

namespace NetMessageServerWpf
{
    public partial class MainWindow : Window
    {
        TcpClient client;

        public MainWindow()
        {
            InitializeComponent();
            this.tcpListener = new TcpListener(IPAddress.Any, 3000);
            this.listenThread = new Thread(new ThreadStart(ListenForClients));
            this.listenThread.Start();
        }

        private void btnSend_Click(object sender, RoutedEventArgs e)
        {
            if(client == null || !client.Connected)
                client = this.tcpListener.AcceptTcpClient();
            msg = txtMessage.Text;
            SendTCP(client);
        }

        public TcpListener tcpListener;
        public Thread listenThread;

        private string msg;

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

        public void SendTCP(TcpClient tcpClient)
        {
            NetworkStream clientStream = tcpClient.GetStream();
            ASCIIEncoding encoder = new ASCIIEncoding();
            byte[] buffer = encoder.GetBytes(this.msg);
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
        }
    }
}

Client:

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

namespace NetClientSideWpf
{
    class Client : Base
    {

        private string messageString;
        public string MessageString
        {
            get { return messageString; }
            set
            {
                messageString = value;
                OnPropertyChanged("MessageString");
            }
        }


        public Client()
        {
            ConnectToServer();
        }

        public void ConnectToServer()
        {
            TcpClient client = new TcpClient();

            IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);

            client.Connect(serverEndPoint);


            NetworkStream clientStream = client.GetStream();

            Thread ServerThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
            ServerThread.Start(client);


        }

        private void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            while (true)
            {
                bytesRead = 0;

                try
                {
                    bytesRead = clientStream.Read(message, 0, 4096);
                }
                catch
                {
                    break;
                }

                if (bytesRead == 0)
                {
                    break;
                }

                ASCIIEncoding encoder = new ASCIIEncoding();
                MessageString = encoder.GetString(message, 0, bytesRead);
            }
        }
    }
}

any help will do! :)

I think first you should start your Listener at the start of your Application. Then look in intervals (Timer) for ingoing connections (TCPListener.Pending http://msdn.microsoft.com/de-de/library/system.net.sockets.tcplistener.pending(v=vs.110).aspx ) If you get a Connection you should save the TCPClient in a List. On Button Click send the Messages to your Clients.

I think it is not the best solution but it is one without Multiple Threads ;-)

I wrote some sample code, hope this help you (not tested):

public partial class MainWindow : Window
{

    private TcpListener _server;
    private List<TcpClient> _connectedClients;

    public MainWindow()
    {
        InitializeComponent();

        _server = new TcpListener(IPAddress.Any, 3000);
        _connectedClients = new List<TcpClient>();
        _server.Start();

        DispatcherTimer timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromSeconds(1); //every 1 sec!
        timer.Tick += timer_Tick;
        timer.Start();
    }

    private void SendMessage(string message)
    {
        ASCIIEncoding encoder = new ASCIIEncoding();
        byte[] buffer = encoder.GetBytes(message);
        foreach (var client in _connectedClients)
        {
            NetworkStream clientStream = client.GetStream();
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
        }
    }


    void timer_Tick(object sender, EventArgs e)
    {
        Debug.WriteLine("Tick");
        Title = "hello";

        if (_server.Pending())
        {
            _connectedClients.Add(_server.AcceptTcpClient());
        }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM