如何建立一台服务器的多个聊天 [英] How to build multiple chat one server
问题描述
大家好
我正在尝试用两种形式(客户端和服务器)构建网络聊天应用程序.
服务器必须能够接受来自许多客户端的连接.
并且每个客户端必须能够与任何其他客户端(包括多个客户端)同时聊天,这可以通过从客户端CheckedListBox进行多个选择来实现.
我被困在如何让客户端选择与之聊天的对象,如何将此参数传递给服务器的问题上
(服务器是否必须保存客户端信息?)
以及如何在新客户端进入或离开时更新客户端和服务器中的列表
请帮帮我
这是我的代码
服务器代码:
Hello guys
I am trying to build network chat application with two forms (client and server).
the server must be able to accept connections from many clients.
and the each client must be able to chat with any other client(including multiple clients at the same time), that can be done with multiple selection from client CheckedListBox.
I am stuck on how to let the client choose whose going to chat with, how to pass this parameters to the server
(does the server haz to save clients info?)
and how to update the list in the client and in server when new client enter or leave
help me please
this is my code
Server code:
<pre lang="msil">public partial class Server : Form
{
public Server()
{
InitializeComponent();
}
private Socket connection; // Socket for accepting a connection
private NetworkStream socketStream; // network data stream
private BinaryWriter writer; // facilitates writing to the stream
private BinaryReader reader; // facilitates reading from the stream
private Guest[] GuestList;
private Thread[] guestThreads;
public Thread UpdateListThread;
public void UpdatList(CheckedListBox chkL)
{
string[] list = new string[chkL1.Items.Count];
for (int i = 0; i<chkL1.Items.Count; i++)
{
}
}
public delegate void DisplayDelegate(string message);
public delegate void AddGuestDelegate(CheckedListBox check_list_box, string str);
public void ChatDisplayMessage(string message)
{
// if modifying TextBox is not thread safe
if (txt_chat.InvokeRequired)
{
// use inherited method Invoke to execute DisplayMessage
// via a delegate
Invoke(new DisplayDelegate(ChatDisplayMessage),
new object[] { message });
} // end if
else // OK to modify TextBox in current thread
txt_chat.Text += message;
}
public void StatusDisplayMessage(string message)
{
// if modifying TextBox is not thread safe
if (txt_status.InvokeRequired)
{
// use inherited method Invoke to execute DisplayMessage
// via a delegate
Invoke(new DisplayDelegate(StatusDisplayMessage),
new object[] { message });
} // end if
else // OK to modify TextBox in current thread
txt_status.Text += message;
}
public void AddGuestToList(CheckedListBox check_list_box,string str)
{
// if modifying list is not thread safe
if (check_list_box.InvokeRequired)
{
// use inherited method Invoke to execute DisplayMessage
// via a delegate
Invoke(new AddGuestDelegate(AddGuestToList),
new object[] { check_list_box,str });
} // end if
else // OK to modify TextBox in current thread
check_list_box.Items.Add(str);
}
//public void UpdatList()
//{
//tvwLists.Nodes.Clear();
//TreeNode rootnde = tvwLists.Nodes.Add("Server");
//SqlDataAdapter da = new SqlDataAdapter();
//System.Data.DataSet ds = new System.Data.DataSet();
//da.SelectCommand = cmd1;
//da.Fill(ds);
//foreach (System.Data.DataRow drw in ds.Tables[0].Rows)
//{
// rootnde.Nodes.Add(drw[ds.Tables[0].Columns["id"]].ToString(), drw[ds.Tables[0].Columns["FullName"]].ToString(), 0);
//}
//}
void AcceptConnections()
{
TcpListener listener;
// wait for a client connection and display the that the client sends
try
{
// create TcpListener
IPAddress local = IPAddress.Parse("127.0.0.1");
listener = new TcpListener(local, 50000);
// TcpListener waits for connection request
listener.Start();
StatusDisplayMessage("Waiting For Guest to connect");
for (int i = 1; i < 10; i++)
{
GuestList[i] = new Guest(listener.AcceptSocket(), this);
guestThreads[i] = new Thread(new ThreadStart(GuestList[i].Run));
guestThreads[i].Start();
StatusDisplayMessage( i + "\n Guests are conected");
}
} // end try
catch (Exception error)
{
MessageBox.Show(error.ToString());
} // end catch
}
private void Server_Load(object sender, EventArgs e)
{
GuestList = new Guest[10];
guestThreads = new Thread[10];
Thread thrd_AcceptConnections = new Thread(new ThreadStart(AcceptConnections));
thrd_AcceptConnections.Start();
}
private void btn_send_Click(object sender, EventArgs e)
{
}
private void Server_FormClosing(object sender, FormClosingEventArgs e)
{
System.Environment.Exit(System.Environment.ExitCode);
}
private void btn_send_Click_1(object sender, EventArgs e)
{
}
}
这是客户
and here is client
public partial class Clients : Form
{
public Clients()
{
InitializeComponent();
}
private NetworkStream output; // stream for receiving data
private BinaryWriter writer; // facilitates writing to the stream
private BinaryReader reader; // facilitates reading from the stream
private Thread readThread; // Thread for processing incoming messages
private string message = "";
public string name;
private delegate void DisplayDelegate(string message);
// method DisplayMessage sets displayTextBox''s Text property
// in a thread-safe manner
private void ChatDisplayMessage(string message)
{
// if modifying displayTextBox is not thread safe
if (txt_chat.InvokeRequired)
{
// use inherited method Invoke to execute DisplayMessage
// via a delegate
Invoke(new DisplayDelegate(ChatDisplayMessage),
new object[] { message });
} // end if
else // OK to modify displayTextBox in current thread
txt_chat.Text += message;
}
private void StatusDisplayMessage(string message)
{
// if modifying displayTextBox is not thread safe
if (txt_status.InvokeRequired)
{
// use inherited method Invoke to execute DisplayMessage
// via a delegate
Invoke(new DisplayDelegate(StatusDisplayMessage),
new object[] { message });
} // end if
else // OK to modify displayTextBox in current thread
txt_status.Text += message;
}
private delegate void DisableControlDelegate(bool value);
private void DisableConnect(bool value)
{
// if modifying inputTextBox is not thread safe
if (btn_connect.InvokeRequired)
{
// use inherited method Invoke to execute DisableInput
// via a delegate
Invoke(new DisableControlDelegate(DisableConnect),
new object[] { value });
} // end if
else // OK to modify inputTextBox in current thread
btn_connect.Enabled = !value;
btn_connect.Text = "Connected";
}
private void DisableInput(bool value)
{
// if modifying inputTextBox is not thread safe
if (txt_Name.InvokeRequired)
{
// use inherited method Invoke to execute DisableInput
// via a delegate
Invoke(new DisableControlDelegate(DisableInput),
new object[] { value });
} // end if
else // OK to modify inputTextBox in current thread
txt_Name.ReadOnly = value;
}
void Connect( )
{
{
TcpClient client;
// instantiate TcpClient for sending data to server
try
{
StatusDisplayMessage("Attempting connection\r\n");
// create TcpClient and connect to server
client = new TcpClient();
client.Connect("127.0.0.1", 50000);
// get NetworkStream associated with TcpClient
output = client.GetStream();
StatusDisplayMessage("Connected\r\n");
DisableConnect(true);
DisableInput(true);
// create objects for writing and reading across stream
writer = new BinaryWriter(output);
reader = new BinaryReader(output);
MethodInvoker action = delegate
{ writer.Write(txt_Name.Text); };
txt_chat.BeginInvoke(action);
do
{
try
{
// read message from server
message = reader.ReadString();
ChatDisplayMessage("\r\n" + message);
} // end try
catch (Exception)
{
// handle exception if error in reading server data
//System.Environment.Exit(System.Environment.ExitCode);
} // end catch
} while (message != "SERVER>>> TERMINATE");
// Step 4: close connection
writer.Close();
reader.Close();
output.Close();
client.Close();
Application.Exit();
} // end try
catch (Exception error)
{
// handle exception if error in establishing connection
MessageBox.Show(error.ToString(), "Connection Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
// System.Environment.Exit(System.Environment.ExitCode);
} // end catch
}
}
private void btn_Send_Click(object sender, EventArgs e)
{
name = txt_Name.Text;
writer.Write(name +">>>" + txt_input.Text);
txt_chat.Text += "\r\n " + name + ">>>" + txt_input.Text;
txt_input.Clear();
}
private void txt_connect_Click(object sender, EventArgs e)
{
readThread = new Thread(new ThreadStart(Connect));
readThread.Start();
}
private void Clients_Load(object sender, EventArgs e)
{
}
private void Clients_FormClosing(object sender, FormClosingEventArgs e)
{
System.Environment.Exit(System.Environment.ExitCode);
}
private void button1_Click(object sender, EventArgs e)
{
}
}
类来宾:
class Guest:
class Guest
{
internal Socket connection; // Socket for accepting a connection
private NetworkStream socketStream; // network data stream
private Server server; // reference to server
private BinaryWriter writer; // facilitates writing to the stream
private BinaryReader reader; // facilitates reading from the stream
public Guest(Socket socket, Server serverValue)
{
connection = socket;
server = serverValue;
// create NetworkStream object for Socket
socketStream = new NetworkStream(connection);
// create Streams for reading/writing bytes
writer = new BinaryWriter(socketStream);
reader = new BinaryReader(socketStream);
} // end constructor
public void write()
{
}
public void Run()
{
//string s = "update";
//for (int i =0; i<server.chkL1.Items.Count; i++)
//{ s = s + server.chkL1.Items[i].ToString(); }
//writer.Write(s);
string str = reader.ReadString();
string name = str;
MethodInvoker action = delegate
{ server.chkL1.Items.Add(str); };
server.chkL1.BeginInvoke(action);
//MethodInvoker action2 = delegate
//{ server.tvwLists.Nodes.Add(str); };
//server.tvwLists.BeginInvoke(action2);
string theReply = "";
do
{
try
{
// read the string sent to the server
theReply = reader.ReadString();
// display the message
server.ChatDisplayMessage("\r\n" + theReply);
} // end try
catch (Exception)
{
// handle exception if error reading data
break;
} // end catch
try
{
}
catch (Exception)
{
// handle exception if error reading data
break;
} // end catch
} while (connection.Connected);
// DisplayMessage("\r\nUser terminated connection\r\n");
// Step 5: close connection
writer.Close();
reader.Close();
socketStream.Close();
connection.Close();
// X must wait for another player to arrive
// close the socket connection
writer.Close();
reader.Close();
socketStream.Close();
connection.Close();
} // end method Run
}
推荐答案
关于实现聊天应用程序的文章不计其数.在文章中搜索"c#聊天"
例如这是搜索结果中出现的第一个;
http://www.codeproject.com/KB/IP/TCPIPChat.aspx [ ^ ]
虽然还有很多……
但是,您基本上需要在服务器上维护UserID和会话令牌的会话列表.
当您要在2个用户之间私下聊天时,服务器充当代理,并使用会话令牌/用户ID,将消息相应地路由到正确的打开连接.
There are countless articles on implementing chat applications. Search the articles for ''c# chat''
e.g. here is the first that appeared in the search results;
http://www.codeproject.com/KB/IP/TCPIPChat.aspx[^]
There are plenty others though......
What you will need to do though, is basically maintain a session list on the server of the UserID and the session token.
The when you want to chat privately between 2 users, the server acts as the proxy and using the session token/userid, routes the messages accordingly to the correct open connections.
这篇关于如何建立一台服务器的多个聊天的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!