• C#编写聊天软件服务端


    
    
     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代码中如何调用C++ C++中如何调用C
    C用函数指针模拟重载 C++重载
    【2019.10.30】意料之外的小黄衫——获得小黄衫感言
    【2019.10.30】SDN上机第1次作业
    【2019.10.17】十天Web前端程序员体验(软件工程实践第五次作业)
    【2019.10.07】《重生之我是程序员》
    【2019.09.30】“福大同好”——原型设计展示~
    【2019.09.30】构建之法《四五八章读后感》
    【2019.09.25】《构建之法》前三章读后感
  • 原文地址:https://www.cnblogs.com/ddwk/p/8742978.html
Copyright © 2020-2023  润新知