码迷,mamicode.com
首页 > Windows程序 > 详细

C#编写聊天软件服务端

时间:2018-04-08 10:21:37      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:前缀   sele   delegate   nbsp   eric   res   main   stop   cas   


 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Net.Sockets;
 6 using System.IO;
 7 
 8 namespace SyncChatServer
 9 {
10     class User
11     {
12         public TcpClient client { get; private set; }
13         public BinaryReader br { get; private set; }
14         public BinaryWriter bw { get; private set; }
15         public string userName { get; set; }
16 
17         public User(TcpClient client)
18         {
19             this.client = client;
20             NetworkStream networkStream = client.GetStream();
21             br = new BinaryReader(networkStream);
22             bw = new BinaryWriter(networkStream);
23         }
24 
25         public void Close()
26         {
27             br.Close();
28             bw.Close();
29             client.Close();
30         }
31 
32     }
33 }

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Windows.Forms;
  9 using System.Net;
 10 using System.Net.Sockets;
 11 using System.Threading;
 12 using System.IO;
 13 
 14 namespace SyncChatServer
 15 {
 16     public partial class MainForm : Form
 17     {
 18         /// <summary>
 19         /// 保存连接的所有用户
 20         /// </summary>
 21         private List<User> userList = new List<User>();
 22 
 23         /// <summary>
 24         /// 服务器IP地址
 25         /// </summary>;
 26         private string ServerIP;
 27 
 28         /// <summary>
 29         /// 监听端口
 30         /// </summary>
 31         private int port;
 32         private TcpListener myListener;
 33 
 34         /// <summary>
 35         /// 是否正常退出所有接收线程
 36         /// </summary>
 37         bool isNormalExit = false;
 38 
 39         public MainForm()
 40         {
 41             InitializeComponent();
 42             lst_State.HorizontalScrollbar = true;
 43             btn_Stop.Enabled = false;
 44             SetServerIPAndPort();
 45         }
 46 
 47         /// <summary>
 48         /// 根据当前程序目录的文本文件‘ServerIPAndPort.txt’内容来设定IP和端口
 49         /// 格式:127.0.0.1:8885
 50         /// </summary>
 51         private void SetServerIPAndPort()
 52         {
 53             FileStream fs = new FileStream("ServerIPAndPort.txt", FileMode.Open);
 54             StreamReader sr = new StreamReader(fs);
 55             string IPAndPort = sr.ReadLine();
 56             ServerIP = IPAndPort.Split(:)[0]; //设定IP
 57             port = int.Parse(IPAndPort.Split(:)[1]); //设定端口
 58             sr.Close();
 59             fs.Close();
 60         }
 61 
 62 
 63         /// <summary>
 64         /// 开始监听
 65         /// </summary>
 66         /// <param name="sender"></param>
 67         /// <param name="e"></param>
 68         private void btn_Start_Click(object sender, EventArgs e)
 69         {
 70             myListener = new TcpListener(IPAddress.Parse(ServerIP), port);
 71             myListener.Start();
 72             AddItemToListBox(string.Format("开始在{0}:{1}监听客户连接", ServerIP, port));
 73             //创建一个线程监客户端连接请求
 74             Thread myThread = new Thread(ListenClientConnect);
 75             myThread.Start();
 76             btn_Start.Enabled = false;
 77             btn_Stop.Enabled = true;
 78         }
 79 
 80         /// <summary>
 81         /// 接收客户端连接
 82         /// </summary>
 83         private void ListenClientConnect()
 84         {
 85             TcpClient newClient = null;
 86             while (true)
 87             {
 88                 try
 89                 {
 90                     newClient = myListener.AcceptTcpClient();
 91                 }
 92                 catch
 93                 {
 94                     //当单击‘停止监听’或者退出此窗体时 AcceptTcpClient() 会产生异常
 95                     //因此可以利用此异常退出循环
 96                     break;
 97                 }
 98                 //每接收一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息;
 99                 User user = new User(newClient);
100                 Thread threadReceive = new Thread(ReceiveData);
101                 threadReceive.Start(user);
102                 userList.Add(user);
103                 AddItemToListBox(string.Format("[{0}]进入", newClient.Client.RemoteEndPoint));
104                 AddItemToListBox(string.Format("当前连接用户数:{0}", userList.Count));
105             }
106 
107         }
108 
109         /// <summary>
110         /// 处理接收的客户端信息
111         /// </summary>
112         /// <param name="userState">客户端信息</param>
113         private void ReceiveData(object userState)
114         {
115             User user = (User)userState;
116             TcpClient client = user.client;
117             while (isNormalExit == false)
118             {
119                 string receiveString = null;
120                 try
121                 {
122                     //从网络流中读出字符串,此方法会自动判断字符串长度前缀
123                     receiveString = user.br.ReadString();
124                 }
125                 catch (Exception)
126                 {
127                     if (isNormalExit == false)
128                     {
129                         AddItemToListBox(string.Format("与[{0}]失去联系,已终止接收该用户信息", client.Client.RemoteEndPoint));
130                         RemoveUser(user);
131                     }
132                     break;
133                 }
134                 AddItemToListBox(string.Format("来自[{0}]:{1}",user.client.Client.RemoteEndPoint,receiveString));
135                 string[] splitString = receiveString.Split(,);
136                 switch(splitString[0])
137                 {
138                     case "Login":
139                         user.userName = splitString[1];
140                         SendToAllClient(user,receiveString);
141                         break;
142                     case "Logout":
143                         SendToAllClient(user,receiveString);
144                         RemoveUser(user);
145                         return;
146                     case "Talk":
147                         string talkString = receiveString.Substring(splitString[0].Length + splitString[1].Length + 2);
148                         AddItemToListBox(string.Format("{0}对{1}说:{2}",user.userName,splitString[1],talkString));
149                         SendToClient(user,"talk," + user.userName + "," + talkString);
150                         foreach(User target in userList)
151                         {
152                             if(target.userName == splitString[1] && user.userName != splitString[1])
153                             {
154                                 SendToClient(target,"talk," + user.userName + "," + talkString);
155                                 break;
156                             }
157                         }
158                         break;
159                     default:
160                         AddItemToListBox("什么意思啊:" + receiveString);
161                         break;
162                 }
163             }
164         }
165 
166         /// <summary>
167         /// 发送消息给所有客户
168         /// </summary>
169         /// <param name="user">指定发给哪个用户</param>
170         /// <param name="message">信息内容</param>
171         private void SendToAllClient(User user, string message)
172         {
173             string command = message.Split(,)[0].ToLower();
174             if (command == "login")
175             {
176                 //获取所有客户端在线信息到当前登录用户
177                 for (int i = 0; i < userList.Count; i++)
178                 {
179                     SendToClient(user, "login," + userList[i].userName);
180                 }
181                 //把自己上线,发送给所有客户端
182                 for (int i = 0; i < userList.Count; i++)
183                 {
184                     if (user.userName != userList[i].userName)
185                     {
186                         SendToClient(userList[i], "login," + user.userName);
187                     }
188                 }
189             }
190             else if(command == "logout")
191             {
192                 for (int i = 0; i < userList.Count; i++)
193                 {
194                     if (userList[i].userName != user.userName)
195                     {
196                         SendToClient(userList[i], message);
197                     }
198                 }
199             }
200         }
201 
202         /// <summary>
203         /// 发送 message 给 user
204         /// </summary>
205         /// <param name="user">指定发给哪个用户</param>
206         /// <param name="message">信息内容</param>
207         private void SendToClient(User user, string message)
208         {
209             try
210             {
211                 //将字符串写入网络流,此方法会自动附加字符串长度前缀
212                 user.bw.Write(message);
213                 user.bw.Flush();
214                 AddItemToListBox(string.Format("向[{0}]发送:{1}", user.userName, message));
215             }
216             catch
217             {
218                 AddItemToListBox(string.Format("向[{0}]发送信息失败",user.userName));
219             }
220         }
221 
222         /// <summary>
223         /// 移除用户
224         /// </summary>
225         /// <param name="user">指定要移除的用户</param>
226         private void RemoveUser(User user)
227         {
228             userList.Remove(user);
229             user.Close();
230             AddItemToListBox(string.Format("当前连接用户数:{0}",userList.Count));
231         }
232 
233         private delegate void AddItemToListBoxDelegate(string str);
234         /// <summary>
235         /// 在ListBox中追加状态信息
236         /// </summary>
237         /// <param name="str">要追加的信息</param>
238         private void AddItemToListBox(string str)
239         {
240             if (lst_State.InvokeRequired)
241             {
242                 AddItemToListBoxDelegate d = AddItemToListBox;
243                 lst_State.Invoke(d, str);
244             }
245             else
246             {
247                 lst_State.Items.Add(str);
248                 lst_State.SelectedIndex = lst_State.Items.Count - 1;
249                 lst_State.ClearSelected();
250             }
251         }
252 
253         /// <summary>
254         /// 停止监听
255         /// </summary>
256         /// <param name="sender"></param>
257         /// <param name="e"></param>
258         private void btn_Stop_Click(object sender, EventArgs e)
259         {
260             AddItemToListBox("开始停止服务,并依次使用户退出!");
261             isNormalExit = true;
262             for (int i = userList.Count - 1; i >= 0; i--)
263             {
264                 RemoveUser(userList[i]);
265             }
266             //通过停止监听让 myListener.AcceptTcpClient() 产生异常退出监听线程
267             myListener.Stop();
268             btn_Start.Enabled = true;
269             btn_Stop.Enabled = false;
270         }
271 
272         /// <summary>
273         /// 关闭窗口时触发的事件
274         /// </summary>
275         /// <param name="sender"></param>
276         /// <param name="e"></param>
277         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
278         {
279             if (myListener != null)
280                 btn_Stop.PerformClick();    //引发 btn_Stop 的Click事件
281         }
282     }
283 }

 

C#编写聊天软件服务端

标签:前缀   sele   delegate   nbsp   eric   res   main   stop   cas   

原文地址:https://www.cnblogs.com/ddwk/p/8742978.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!