Мульти-клиентский односерверный чат C#
Уважаемые Все Разработчики,
Я новичок в этой области.Моя задача-создать приложение для диаграмм с несколькими клиентами и одним сервером с использованием C#. Это приложение, которое позволяет серверу отвечать на сообщение от клиента к клиенту, который отправляет сообщение в одной форме. Я пытался понять этот пример Многопоточный Чат-Сервер[^] .
но в моем проекте, если к этому серверу подключено более одного клиента, я просто могу отправить данные последнему клиенту, который подключился к этому серверу. В моем случае моя цель заключается в том, что этот сервер должен иметь возможность отправлять данные клиенту, которого я выбрал.
Что я уже пробовал:
это мой код в форму 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"; } } }
в 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; } } }
Richard MacCutchan
Ни у кого здесь не будет времени прочитать весь этот код и попытаться понять, что он делает. Пожалуйста, отредактируйте свой вопрос и удалите код, который не связан с проблемой, и четко покажите, где возникает проблема.
Member 14150101
Спасибо за ваш совет, я воссоздам свой вопрос.