多客户端单服务器聊天C# [英] Multi-client single server chat C#

查看:77
本文介绍了多客户端单服务器聊天C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

亲爱的所有开发者,



我是这个领域的新手。我的任务是创建一个使用C#的多客户端和单服务器图表应用程序。此应用程序,允许服务器将消息从客户端回复到以一种形式发送消息的客户端。我试图找到这个例子 多线程聊天服务器 [ ^ ]。



但是,在我的项目中,如果有多个客户端连接到此服务器,我只能将数据发送到连接到此服务器的最后一个客户端。在我的情况下,我的目的是这个服务器必须能够将数据发送到我选择的客户端。



我尝试过:



这是我在form1.cs中的代码



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

命名空间serverchat
{
public partial class Form1:Form
{
private int count;
Dictionary< string,TcpClient> clientDict;
List< TcpClient>客户端列表;
private TcpListener tcpServer;
private TcpClient tcpClient;
private Thread;
private ArrayList formArray = new ArrayList();
private ArrayList threadArray = new ArrayList();
public delegate void ChangedEventHandler(object sender,EventArgs e);
公共事件ChangedEventHandler已更改;
public delegate void SetListBoxItem(String str,String type);

私有TcpClient客户端;
private NetworkStream clientStream;
public delegate void SetTextCallback(string s);
//私人Form1所有者;

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 = 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();

//继续接受客户端连接
而(true)
{

//连接新客户端,调用Event来处理它。
线程t =新线程(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();

//调用Delegate函数更新树视图
UpdateClientList(remoteIP +:+ remotePort,Add);

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

//创建状态对象。
StateObject state = new StateObject();
state.workSocket = connectedClient.Client;

//调用异步接收函数
connectedClient.Client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
new AsyncCallback(OnReceive),state);



}
private void UpdateClientList(字符串str,字符串类型)
{
//需要InvokeRequired比较的线程ID
//将线程调用到创建线程的线程ID。
//如果这些线程不同,则返回true。
if(this.tvClientList.InvokeRequired)
{
SetListBoxItem d = new SetListBoxItem(UpdateClientList);
this.Invoke(d,new object [] {str,type});
}
else
{
//如果type为Add,则在树视图中添加客户端信息
if(type.Equals(Add))
{
this.tvClientList.Nodes [0] .Nodes.Add(str);
}
//否则从树视图中删除客户端信息
else
{
foreach(this.tvClientList.Nodes [0] .Nodes中的TreeNode n)
{
if(n.Text.Equals(str))
this.tvClientList.Nodes.Remove(n);
}
}

}
}

private void tvClientList_DoubleClick(object sender,System.EventArgs e)
{
//打开隐藏对话框
// if(!((ChatDialog)formArray [index])。可见)
//((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)
{
//验证端口号
try
{
int port;
port = Int32.Parse(tbPort.Text);

string cx = tbPort.Text.ToString();

StartServer();

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

}
catch(exception ex)
{
MessageBox.Show(请输入正确的端口号!!!);
cbStartStop.Checked = false;
}
}

其他
{
StopServer();
}

}

private void SetText(字符串文本)
{
//需要InvokeRequired比较$ b的线程ID $ b //调用线程到创建线程的线程ID。
//如果这些线程不同,则返回true。
String remotePort =((IPEndPoint)tcpClient.Client.RemoteEndPoint).Port.ToString();
if(this.rtbchattting.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d,new object [] {text});
}
其他
{
this.rtbchattting.SelectionColor = Color.Blue;
this.rtbchattting.SelectedText = remotePort +:+ text +\ n;
}
}


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

//从异步状态对象中检索状态对象和处理程序套接字
//。
StateObject state =(StateObject)ar.AsyncState;
套接字处理程序= state.workSocket;
int bytesRead;

if(handler.Connected)
{

//从客户端套接字读取数据。
try
{
bytesRead = handler.EndReceive(ar);
if(bytesRead> 0)
{
//可能有更多数据,因此存储到目前为止收到的数据。
state.sb.Remove(0,state.sb.Length);
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead));

//在富文本框中显示文本
content = state.sb.ToString();
SetText(内容);

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

}
}

catch(SocketException socketException)
{
// WSAECONNRESET,另一方不礼貌地收盘
如果(socketException.ErrorCode == 10054 ||((socketException.ErrorCode!= 10004)&&(socketException.ErrorCode!= 10053)))
{
//完成断开连接请求。
String remoteIP =((IPEndPoint)handler.RemoteEndPoint).Address.ToString();
String remotePort =((IPEndPoint)handler.RemoteEndPoint).Port.ToString();
//this.owner.DisconnectClient(remoteIP,remotePort);

handler.Close();
handler = null;

}
}
//吃掉异常......嗯,我喜欢吃!!!
catch(异常异常)
{
MessageBox.Show(exception.Message +\ n+ + exception.StackTrace);

}
}
}

公共类StateObject
{
//客户端套接字。
public Socket workSocket = null;
//接收缓冲区的大小。
public const int BufferSize = 1024;
//接收缓冲区。
public byte [] buffer = new byte [BufferSize];
//收到的数据字符串。
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(输入材料名称请。);
//dataGridView1.Rows.Clear();
}

else {




connectedClient.Client.Send(chatts);
//并使用选定的客户端。



}





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

}





}
}








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;
}


}
}

解决方案

你会是最好使用 SignalR [ ^ ]。 Microsoft文档包括示例聊天应用 [ ^ ]。



这是一个关于CodeProject的示例聊天应用程序文章你想要什么: SignalChat:WPF& SignalR聊天应用程序 [ ^ ]

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;
        }


    }
}

解决方案

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[^]


这篇关于多客户端单服务器聊天C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆