程序简介
好久没写博客了,最近时间比较充足.于是便打算把之前的聊天程序功能改进下,增加了一个服务端给客户端群发信息的功能.
原理
首先我们需要获取连接客户端的IP和Port,并添加到客户端列表里作为每个客户端的唯一标识.然后通过相应客户端的Socket.Send()方法将信息发送出去.
服务端给客户端的信息群发与服务端给单个客户端的信息发送原理是一样的,通过遍历客户端列表里的所有客户端标识,然后把信息一个个发送出去.
界面设计 - 客户端

界面设计 - 服务端

代码实施 - 客户端
客户端没有做什么功能改进,这里就不贴代码了,需要看的学友可以到随笔后面下载源代码.
代码实施 - 服务端
这里将手动输入服务端IPv4地址改为了程序自动获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public IPAddress GetLocalIPv4Address() { IPAddress localIPv4 = null; IPAddress[] ipAddressList = Dns.GetHostAddresses(Dns.GetHostName()); foreach (IPAddress ipAddress in ipAddressList) { if (ipAddress.AddressFamily == AddressFamily.InterNetwork) { localIPv4 = ipAddress; } else continue; } return localIPv4; }
|
为了方便后期给所有访问的客户端群发信息,我们需要用过通过监听客户端来获取所有访问客户端的IP地址和端口号,并组成每个访问客户端的唯一标识clientName 用于显示在客户端列表上;客户端唯一标识还有个作用就是服务端可以选择性的给单独某个客户端发送信息.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
Socket socConnection = null; string clientName = null; IPAddress clientIP; int clientPort;
private void WatchConnecting() { while (true) { try { socConnection = socketWatch.Accept(); } catch (Exception ex) { txtMsg.AppendText(ex.Message); break; } clientIP = (socConnection.RemoteEndPoint as IPEndPoint).Address; clientPort = (socConnection.RemoteEndPoint as IPEndPoint).Port; clientName = "IP: " + clientIP +" Port: "+ clientPort; lstClients.Items.Add(clientName); dicSocket.Add(clientName, socConnection);
ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRecMsg); Thread thread = new Thread(pts); thread.IsBackground = true; thread.Start(socConnection); txtMsg.AppendText("IP: " + clientIP + " Port: " + clientPort + " 的客户端与您连接成功,现在你们可以开始通信了...\r\n"); } }
|
服务端向客户端发送信息,在没有选择具体某个客户端的情况下,默认群发. 如果选择了具体某个客户端,则单独向该客户端发送信息.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
private void ServerSendMsg(string sendMsg) { sendMsg = txtSendMsg.Text.Trim(); byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg); if (!string.IsNullOrEmpty(lstClients.Text.Trim())) { dicSocket[lstClients.Text.Trim()].Send(arrSendMsg); txtMsg.AppendText("您在 " + GetCurrentTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的客户端发送了:\r\n" + sendMsg + "\r\n"); } else { for (int i = 0; i < lstClients.Items.Count; i++) { dicSocket[lstClients.Items[i].ToString()].Send(arrSendMsg); } txtMsg.AppendText("您在 " + GetCurrentTime() + " 群发了信息:\r\n" + sendMsg + " \r\n"); } }
|
运行程序
1.首先启动服务端并连接各个客户端



2.服务端向所有客户端群发信息



3.向指定的客户端发送信息


这样,服务端向客户端群发信息的功能就做好了.如果大家感兴趣,可以结合第2篇-文件发送 来做个服务端向客户端群发文件的功能 :)
附上源代码
服务端ChatServer3.zip 客户端 ChatClient3.zip
转自:https://www.cnblogs.com/longwu/archive/2012/07/02/2572648.html