using System; using System.Collections.Generic; using System.Collections.Concurrent; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Net; using System.Net.Http; using System.Net.Sockets; using System.Threading; namespace SocketStudy.ServerApp { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { //服务监听 private TcpListener _tcpServer = null; //存放活动客户端连接字典 private ConcurrentDictionary _remoteClientDic = new ConcurrentDictionary(); //监听线程 private Thread _listenerThread; public MainWindow() { InitializeComponent(); } /// /// 窗口呈现完毕事件 /// private void Window_ContentRendered(object sender, EventArgs e) { //初始化客户端 comboBox_Clients.Items.Clear(); comboBox_Clients.Items.Insert(insertIndex: 0,"广播"); comboBox_Clients.SelectedIndex = 0; //默认服务器网址 comboBox_ServerAddress.Items.Insert(0, "本机所有IP4"); comboBox_ServerAddress.SelectedIndex = 0; var ip4Addresses = Dns.GetHostAddresses(Dns.GetHostName(), AddressFamily.InterNetwork) ?? new IPAddress[] { IPAddress.Any}; foreach (var ip in ip4Addresses) { comboBox_ServerAddress.Items.Add(ip); } } /// /// 启动服务 /// private void btn_Start_Click(object sender, RoutedEventArgs e) { if (_tcpServer?.Server?.IsBound ?? false) { WriteLog("服务正在运行,无需启动!"); return; } IPAddress serverAddress = IPAddress.Any; if (comboBox_ServerAddress.SelectedValue.ToString() != "本机所有IP4") { serverAddress = (IPAddress)comboBox_ServerAddress.SelectedValue; } int serverPort = 6605; if (!int.TryParse(textBox_ServerPort.Text.Trim(), out serverPort)) { WriteLog("端口号错误"); return; } else { if (serverPort <= 1024 || serverPort >= 65535) { WriteLog("端口号错误:必须在 1205-65534"); return; } } WriteLog("启动服务..."); _tcpServer = new TcpListener(serverAddress, serverPort); _tcpServer.Start(); WriteLog("服务成功启动!"); //开启监听线程 _listenerThread = new Thread(AcceptTcpClient); _listenerThread.IsBackground = true; _listenerThread.Start(_tcpServer); //控件操作 comboBox_ServerAddress.IsEnabled = false; textBox_ServerPort.IsEnabled = false; WriteLog("服务启动完毕!"); } /// /// 停止服务 /// private void btn_Stop_Click(object sender, RoutedEventArgs e) { if (_tcpServer == null || _tcpServer.Server.IsBound == false) { WriteLog("服务正未运行,无法停止!"); return; } //关闭客户端 foreach (var item in _remoteClientDic) { if (item.Value.Connected) { item.Value.Close(); item.Value.Dispose(); } } WriteLog("停止服务..."); _tcpServer?.Stop(); //清空客户端 _remoteClientDic.Clear(); ResetClientsItems(); //恢复控制状态 comboBox_ServerAddress.IsEnabled = true; textBox_ServerPort.IsEnabled = true; WriteLog("服务停止完成!"); } /// /// 发送数据 /// private void btn_Send_Click(object sender, RoutedEventArgs e) { if (_remoteClientDic.Count == 0 || comboBox_Clients.Items.Count ==0) { WriteLog("没有正在连接的客户端,请先使用客户端连接到本服务器!"); return; } var clientForSend=new List(); var selectedItemValue = comboBox_Clients.SelectedValue as string; if (selectedItemValue == "广播") { clientForSend = _remoteClientDic.Where(q => q.Value.Connected == true).Select(d => d.Value).ToList(); } else { var queryItem = _remoteClientDic.FirstOrDefault(q => q.Key == comboBox_Clients.SelectedValue.ToString()); clientForSend.Add(queryItem.Value); } foreach (var client in clientForSend) { try { var message = textBox_SendData.Text.Trim(); byte[] buffer = Encoding.UTF8.GetBytes(message); NetworkStream networkStream = client.GetStream(); networkStream.Write(buffer, 0, buffer.Length); WriteLog($"发送数据成功:{message}"); } catch (Exception ex) { WriteLog($"{ex.Message}"); } finally { } } } /// /// 写日志信息 /// private void WriteLog(string message) { Dispatcher.BeginInvoke(new Action(() => { richTextBox_Log.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} {message}{System.Environment.NewLine}"); richTextBox_Log.ScrollToEnd(); Console.WriteLine(message); })); } /// /// 重新设置客户端列表项 /// private void ResetClientsItems() { Dispatcher.BeginInvoke(new Action(() => { //字典中的远程客户端同步到下拉列表项 foreach (var clientItem in _remoteClientDic) { if (!comboBox_Clients.Items.Contains(clientItem.Key)) { comboBox_Clients.Items.Add(clientItem.Key); } } //从下拉项中移除已经下线的远程客户端 for (int i = 0; i < comboBox_Clients.Items.Count; i++) { var itemValue = comboBox_Clients.Items[i] as string; if (itemValue == null) { continue; } if (itemValue.Contains("广播")) { continue; } if (!_remoteClientDic.ContainsKey(itemValue)) { comboBox_Clients.Items.Remove(comboBox_Clients.Items[i]); } } })); } /// /// 监听客户端连接方法 /// private void AcceptTcpClient(Object? tcpListener) { TcpListener? tcpServer = tcpListener as TcpListener; if (tcpServer == null) { WriteLog("调用监听连接方法时,参数为null,将监听不到客户端连接!"); return; } WriteLog("开始监听客户端连接..."); //无限循环:处理多个客户端连接 while (_tcpServer.Server.IsBound) { TcpClient remoteClientSocket = null; try { //阻塞等待操作 remoteClientSocket = _tcpServer.AcceptTcpClient(); WriteLog("接收到连接请求..."); var remoteEndPoint = remoteClientSocket.Client.RemoteEndPoint as IPEndPoint; if (remoteEndPoint == null) { continue; } string ipAndPortKey = $"{remoteEndPoint.Address}:{remoteEndPoint.Port}"; if (!_remoteClientDic.ContainsKey(ipAndPortKey)) { _remoteClientDic.TryAdd(ipAndPortKey, remoteClientSocket); } ResetClientsItems(); //接收数据线程 Thread receviceThread = new Thread(ReciveData); receviceThread.IsBackground = true; receviceThread.Start(remoteClientSocket); WriteLog("连接请求处理完成!"); } catch (SocketException socketException) { //移除客户端 remoteClientSocket?.Close(); remoteClientSocket?.Dispose(); WriteLog($"出现Socket异常:{socketException.Message}"); } catch (Exception ex) { //移除客户端 remoteClientSocket?.Close(); remoteClientSocket?.Dispose(); WriteLog($"出现异常:{ex.Message}"); } finally { } } //清空客户端 _remoteClientDic.Clear(); ResetClientsItems(); WriteLog($"监听客户端连接的线程,退出!线程托管Id={Thread.CurrentThread.ManagedThreadId}"); } /// /// 接收客户端数据方法 /// private void ReciveData(object? tcpClient) { if (tcpClient == null) { WriteLog($"接收数据出错:客户端参数{nameof(tcpClient)}为 null"); return; } TcpClient remoteClient = (TcpClient)tcpClient; IPEndPoint? remoteEndPoint = remoteClient.Client?.RemoteEndPoint as IPEndPoint; string remoteClientKey = $"{remoteEndPoint?.Address}:{remoteEndPoint?.Port}"; try { while (remoteClient.Connected) { NetworkStream remoteClientStream = remoteClient.GetStream(); byte[] buffer = new byte[8096]; //阻塞等待操作 var readCount = remoteClientStream.Read(buffer, 0, buffer.Length); //为0代表客户端主动发送关闭操作数据。平常时,即使发送0长度数据也不会是0 if (readCount == 0) { remoteClientStream.Close(); remoteClientStream.Dispose(); WriteLog($"接收[{remoteClientKey}]关闭连接请求数据。"); break; } var message = Encoding.UTF8.GetString(buffer, 0, readCount); WriteLog($"接收到[{remoteClientKey}]数据:{message}"); } } catch (SocketException socketException) { WriteLog($"接收到[{remoteClientKey}]数据异常:{socketException.Message}"); } catch (Exception ex) { WriteLog($"接收到[{remoteClientKey}]数据异常:{ex.Message}"); } finally { remoteClient.Close(); remoteClient.Dispose(); _remoteClientDic.Remove(remoteClientKey, out var sss); ResetClientsItems(); WriteLog($"接收[{remoteClientKey}]数据的线程退出:线程托管Id={Thread.CurrentThread.ManagedThreadId}"); } } } }