Click here to Skip to main content
16,018,264 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Dear All Developer,

I am newbie at this field.My task is creat a multi-client and single server chart app using C#. This app, which allow server to reply the message from client to client who send the message at one form. I was trying to figured this example Multithreaded Chat Server[^] .

but, in my project, if more than one client connected to this server, i just able send the data to the last client who connected to this server. In my case, my purpose is this server must be able send the data to the client which i selected.

What I have tried:

this is my code in form1.cs

using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;

namespace serverchat
{
    public partial class Form1 : Form
    {
        private int count;
        Dictionary<string, TcpClient> clientDict;
        List<TcpClient> clientList;
        private TcpListener tcpServer;
        private TcpClient tcpClient;
        private Thread th;
        private ArrayList formArray = new ArrayList();
        private ArrayList threadArray = new ArrayList();
        public delegate void ChangedEventHandler(object sender, EventArgs e);
        public event ChangedEventHandler Changed;
        public delegate void SetListBoxItem(String str, String type);

        private TcpClient client;
        private NetworkStream clientStream;
        public delegate void SetTextCallback(string s);
        //private Form1 owner;

        public TcpClient connectedClient
        {
            get { return client; }
            set { client = value; }

        }


        public Form1()
        {
            InitializeComponent();

            // memasukkan data dari client yang baru ke dalam tree view
            Changed += new ChangedEventHandler(ClientAdded);
            TreeNode node;
            node = tvClientList.Nodes.Add("list client");
        }

        public void StartServer() // memulai server
        {
            tbPort.Enabled = false;
            th = new Thread(new ThreadStart(StartListen));
            th.Start();
        }

        public void StartListen() 
        {

            IPAddress localAddr = IPAddress.Parse("127.0.0.1");

            tcpServer = new TcpListener(localAddr, Int32.Parse(tbPort.Text));
            tcpServer.Start();

            // Keep on accepting Client Connection
            while (true)
            {

                // New Client connected, call Event to handle it.
                Thread t = new Thread(new ParameterizedThreadStart(NewClient));
                tcpClient = tcpServer.AcceptTcpClient();
                t.Start(tcpClient);
                count++;

            }

        }

        public void StopServer()
        {
            if (tcpServer != null)
            {
                tvClientList.Nodes[0].Nodes.Clear();

                // Abort Listening Thread and Stop listening
                th.Abort();
                tcpServer.Stop();
            }
            tbPort.Enabled = true; 
        }
        
        public void NewClient(Object obj)
        {
            ClientAdded(this, new MyEventArgs((TcpClient)obj));
        }

        public void ClientAdded(object sender, EventArgs e)
        {
            tcpClient = ((MyEventArgs)e).clientSock;
            String remoteIP = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString();
            String remotePort = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Port.ToString();
           
            // Call Delegate Function to update Tree View
            UpdateClientList(remoteIP + " : " + remotePort, "Add");

            connectedClient = tcpClient;
            clientStream = tcpClient.GetStream();

            // Create the state object.
            StateObject state = new StateObject();
            state.workSocket = connectedClient.Client;

            //Call Asynchronous Receive Function
            connectedClient.Client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(OnReceive), state);

           

        }
        private void UpdateClientList(string str, string type)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.tvClientList.InvokeRequired)
            {
                SetListBoxItem d = new SetListBoxItem(UpdateClientList);
                this.Invoke(d, new object[] { str, type });
            }
            else
            {
                // If type is Add, the add Client info in Tree View
                if (type.Equals("Add"))
                {
                    this.tvClientList.Nodes[0].Nodes.Add(str);
                }
                // Else delete Client information from Tree View
                else
                {
                    foreach (TreeNode n in this.tvClientList.Nodes[0].Nodes)
                    {
                        if (n.Text.Equals(str))
                            this.tvClientList.Nodes.Remove(n);
                    }
                }

            }
        }

        private void tvClientList_DoubleClick(object sender, System.EventArgs e)
        {
              // Open Hidden Dialog Box
           // if (!((ChatDialog)formArray[index]).Visible)
            //    ((ChatDialog)formArray[index]).Show();
        }

        private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
        {
            StopServer();

        }

        private void cbStartStop_CheckedChanged_1(object sender, EventArgs e)
        {
            if (cbStartStop.Checked == true)
            {
                // validate the port number
                try
                {
                    int port;
                    port = Int32.Parse(tbPort.Text);

                    string cx = tbPort.Text.ToString();

                    StartServer();

                    MessageBox.Show("connect!!!" + cx);

                }
                catch (Exception ex)
                {
                    MessageBox.Show("Please enter the correct port number!!!");
                    cbStartStop.Checked = false;
                }
            }

            else
            {
                StopServer();
            }

        }

        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            String remotePort = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Port.ToString();
            if (this.rtbchattting.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.rtbchattting.SelectionColor = Color.Blue;
                this.rtbchattting.SelectedText = remotePort +" : " + text +"\n";
            }
        }


        public void OnReceive(IAsyncResult ar)
        {
            String content = String.Empty;

            // Retrieve the state object and the handler socket
            // from the asynchronous state object.
            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.workSocket;
            int bytesRead;

            if (handler.Connected)
            {

                // Read data from the client socket. 
                try
                {
                    bytesRead = handler.EndReceive(ar);
                    if (bytesRead > 0)
                    {
                        // There  might be more data, so store the data received so far.
                        state.sb.Remove(0, state.sb.Length);
                        state.sb.Append(Encoding.ASCII.GetString(
                                         state.buffer, 0, bytesRead));

                        // Display Text in Rich Text Box
                        content = state.sb.ToString();
                        SetText(content);

                        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                            new AsyncCallback(OnReceive), state);

                    }
                }

                catch (SocketException socketException)
                {
                    //WSAECONNRESET, the other side closed impolitely
                    if (socketException.ErrorCode == 10054 || ((socketException.ErrorCode != 10004) && (socketException.ErrorCode != 10053)))
                    {
                        // Complete the disconnect request.
                        String remoteIP = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();
                        String remotePort = ((IPEndPoint)handler.RemoteEndPoint).Port.ToString();
                        //this.owner.DisconnectClient(remoteIP, remotePort);

                        handler.Close();
                        handler = null;

                    }
                }
                // Eat up exception....Hmmmm I'm loving eat!!!
                catch (Exception exception)
                {
                    MessageBox.Show(exception.Message + "\n" + exception.StackTrace);

                }
            }
        }

        public class StateObject
        {
            // Client  socket.
            public Socket workSocket = null;
            // Size of receive buffer.
            public const int BufferSize = 1024;
            // Receive buffer.
            public byte[] buffer = new byte[BufferSize];
            // Received data string.
            public StringBuilder sb = new StringBuilder();
        }

        private void Btn_Kirim_Click(object sender, EventArgs e)
        {
            byte[] chatts;
            chatts = Encoding.ASCII.GetBytes(tbSendChat.Text);
            if (String.IsNullOrEmpty(tbNoClient.Text))
            {
            MessageBox.Show("Enter Material Name Please.");
            //dataGridView1.Rows.Clear();
            }
            
            else{

                
                   

                        connectedClient.Client.Send(chatts);
                        //and use selected client.
                    
                

            }
            
            
            
            

            rtbchattting.SelectionColor = Color.IndianRed;
            rtbchattting.SelectedText = "\nServer:     " + tbSendChat.Text + "\n";
            
        }

       


       
    }
}




in MyEventArgs.cs

namespace serverchat
{
    class MyEventArgs : EventArgs
    {
        private TcpClient sock;
        public TcpClient clientSock
        {
            get { return sock; }
            set { sock = value; }
        }

        public MyEventArgs(TcpClient tcpClient)
        {
            sock = tcpClient;
        }


    }
}
Posted
Updated 19-Feb-19 11:54am
Comments
Richard MacCutchan 19-Feb-19 4:05am    
No one here will have the time to read all that code and try to figure out what it is doing. Please edit your question and remove the code that is not related to the problem, and show clearly where the problem occurs.
Member 14150101 22-Feb-19 3:23am    
Thanks for your advice, i will re-create my question.

1 solution

You would be better off using SignalR[^]. Microsoft docs include a sample chat app[^].

Here is a sample chat app article here on CodeProject that is doing exactly what you want: SignalChat: WPF & SignalR Chat Application[^]
 
Share this answer
 
Comments
Maciej Los 20-Feb-19 4:28am    
5ed!
Graeme_Grant 20-Feb-19 9:28am    
Thanks :)
Member 14150101 22-Feb-19 3:23am    
thanks for your suggestion.

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