c#Socket学习,使用Socket创建一个在线聊天,服务端功能实现,(3)

服务功能实现

技术点

  • 传输方式:TCP 协议保证数据有序、无丢失传输,通过字节流拆包 / 封包机制解决粘包 / 半包问题。
  • 协议格式:采用 “4 字节长度头 + JSON 消息体” 的二进制协议,解决 TCP 粘包 / 半包问题。
  • 消息格式:MessageStyle 消息格式,所有的消息都使用MessageStyle,包裹将消息放到Message 中,然后设置不同的 public MessageTypeEnum Type { get; set; }

项目执行流程

  1. 程序入口执行:调用Main方法,依次执行RegisterApplicationEventsInitializeSocket,进行事件注册和socket初始化
  2. 启动AcceptClientConnections线程:循环调用_serverSocket.Accept()阻塞监听客户端连接请求,该线程为后台线程,不阻塞主线程
  3. 链接完成后使用HandleConsoleInput启动控制台命令

客户端连接

  1. 接收客户端连接AcceptClientConnections
    调用GenerateUniqueClientId生成CLIENT_+GUID格式的唯一客户端 ID。
    创建ClientInfo对象,存储客户端 Socket、ID、最后活跃时间、连接状态等信息。
    加锁将ClientInfo添加到_clients字典,线程安全。
    控制台输出客户端连接信息(ID、IP、端口)。

  2. 发送欢迎消息
    调用SendWelcomeMessageToClient,发送欢迎消息,通过SendMessageToClient按 “4 字节长度头 + JSON 消息体” 协议发送给客户端,完成客户端身份初始化。
    启动客户端消息处理线程

                    // 启动处理客户端消息的线程
                    Thread clientThread = new Thread(() => HandleClient(clientId));
                    clientThread.IsBackground = true;
                    clientThread.Start();

为当前客户端分配独立的 private static void HandleClient(string clientId) 线程。
3. 然后接收和处理客户端发来的消息 ProcessClientMessage(clientId, message);
4. 解析数据,先读取四字节长度的消息,然后一直接收并解析数据

          //  读取4字节的消息长度
          int lengthBytesRead = 0;
          while (lengthBytesRead < 4)
          {
              int read = clientInfo.Socket.Receive(
                  lengthBuffer,
                  lengthBytesRead,
                  4 - lengthBytesRead,
                  SocketFlags.None);

              if (read == 0)
              {
                  // 客户端断开连接
                  throw new SocketException((int) SocketError.ConnectionReset);
              }

              lengthBytesRead += read;
          }

          // 将4字节转换为消息长度(网络字节序转主机字节序)
          int messageLength = BitConverter.ToInt32(lengthBuffer, 0);
          messageLength = IPAddress.NetworkToHostOrder(messageLength);

          //  根据长度读取完整消息
          messageBuffer.SetLength(0);
  1. 处理各种消息
        private static void HandleTextMessage(string clientId, MessageStyle message)
        private static void HandleBroadcastMessage(string clientId, MessageStyle message)
        private static void HandlePrivateMessage(string clientId, MessageStyle message)
        private static void HandleSetUserName(string clientId, MessageStyle message)
			 等等-----
  1. 使用控制台发送命令
        /// <summary>
        /// 处理控制台输入
        /// </summary>
        private static void HandleConsoleInput()
        {
            Console.WriteLine("\n服务器命令:");
            DeaultConsoleLine();

            while (true)
            {
                try
                {
                    string input = Console.ReadLine();
                    if (string.IsNullOrWhiteSpace(input))
                        continue;

                    var parts = input.Trim().Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Length == 0) continue;

                    string command = parts[0].ToUpper();
                    string[] args = parts.Length > 1 ? parts.Skip(1).ToArray() : new string[0];

                    switch (command)
                    {
                        case "/EXIT":
                            break;        

                        default:
                            Console.WriteLine("未知命令,输入 /help 查看可用命令");
                            break;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"处理命令时出错: {ex.Message}");
                }
            }
        }

项目引用

在这里插入图片描述

在这里插入图片描述

基础工具代码

仅需要生成客户端id这一个工具代码,只有一个地方使用到了,所以也可以删掉直接写到用地方。

        /// <summary>
        /// 生成客户端ID
        /// </summary>
        private static string GenerateClientId()
        {
            lock (_lock)
            {
                return $"CLIENT_{Guid.NewGuid():N}";
            }
        }

变量创建

        /// <summary>
        /// socket
        /// </summary>
        private static Socket _serverSocket;

        /// <summary>
        /// 客户端列表
        /// </summary>
        private static Dictionary<string, ClientInfo> _clients = new Dictionary<string, ClientInfo>();

        /// <summary>
        /// 线程锁
        /// </summary>
        private static object _lock = new object();

        /// <summary>
        /// 端口
        /// </summary>
        private static int Port = 23841;

socket链接

        /// <summary>
        /// 初始化socket
        /// </summary>
        private static void InitSocket()
        {
            _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipNode = new IPEndPoint(IPAddress.Any, Port);

            try
            {
                _serverSocket.Bind(ipNode);
                _serverSocket.Listen(10);
                Console.WriteLine($"服务器已启动,监听端口: {Port}");
                Console.WriteLine("等待客户端连接...");

                // 启动接受连接的线程
                Thread acceptThread = new Thread(AcceptClients);
                acceptThread.IsBackground = true;
                acceptThread.Start();

                // 处理控制台输入
                HandleConsoleInput();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"服务器启动失败: {ex.Message}");
            }
        }
        /// <summary>
        /// 接受客户端连接的线程
        /// </summary>
        private static void AcceptClients()
        {
            while (true)
            {
                try
                {
                    Socket clientSocket = _serverSocket.Accept();

                    // 生成客户端ID
                    string clientId = GenerateClientId();

                    // 创建客户端信息
                    ClientInfo clientInfo = new ClientInfo
                    {
                        ClientId = clientId,
                        Socket = clientSocket,
                        LastActiveTime = DateTime.Now,
                        IsConnected = true
                    };

                    // 添加到客户端字典
                    lock (_lock)
                    {
                        _clients[clientId] = clientInfo;
                    }

                    IPEndPoint clientEndPoint = (IPEndPoint)clientSocket.RemoteEndPoint;
                    Console.WriteLine($"客户端 {clientId} 已连接,IP: {clientEndPoint.Address}:{clientEndPoint.Port}");

                    // 发送欢迎消息和客户端ID
                    SendWelcomeMessage(clientId);

                    // 启动处理客户端消息的线程
                    Thread clientThread = new Thread(() => HandleClient(clientId));
                    clientThread.IsBackground = true;
                    clientThread.Start();
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"接受客户端连接时出错: {ex.Message}");
                }
            }
        }


        /// <summary>
        /// 事件注册
        /// </summary>
        private static void EventRegistration()
        {
            AppDomain.CurrentDomain.ProcessExit += (s, e) =>
            {
                try
                {
                    if (_serverSocket != null && _serverSocket.Connected)
                    {
                        _serverSocket.Shutdown(SocketShutdown.Both);
                    }
                    _serverSocket?.Close();
                    Console.WriteLine("服务器Socket已释放");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"释放服务器Socket失败: {ex.Message}");
                }
            };
        }

并且在Main中调用

        static void Main(string[] args)
        {
            EventRegistration();
            InitSocket();
        }

事件处理

用户管理

发送欢迎消息,在用户连接之后
        /// <summary>
        /// 发送欢迎消息
        /// </summary>
        private static void SendWelcomeMessage(string clientId)
        {
            try
            {
                ClientInfo clientInfo;
                lock (_lock)
                {
                    if (!_clients.TryGetValue(clientId, out clientInfo))
                    {
                        return;
                    }
                }

                WelComMessageModel welComMessage = new WelComMessageModel("欢迎连接到Socket服务器!");

                MessageStyle messageStyle = new MessageStyle
                (
                    MessageTypeEnum.Welcome,
                    clientInfo.ClientId,
                    JsonConvert.SerializeObject(welComMessage)
                );

                SendMessage(clientInfo.ClientId, JsonConvert.SerializeObject(messageStyle));
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发送欢迎消息失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 移除客户端
        /// </summary>
        private static void RemoveClient(string clientId)
        {
            lock (_lock)
            {
                if (_clients.ContainsKey(clientId))
                {
                    try
                    {
                        _clients[clientId].Socket.Shutdown(SocketShutdown.Both);
                        _clients[clientId].Socket.Close();
                    }
                    catch { }

                    _clients.Remove(clientId);
                    Console.WriteLine($"客户端 {clientId} 已从列表中移除");
                }
            }
        }

消息事件

消息接收与消息预处理

        /// <summary>
        /// 处理客户端消息
        /// </summary>
        private static void HandleClient(string clientId)
        {
            ClientInfo clientInfo;
            lock (_lock)
            {
                if (!_clients.TryGetValue(clientId, out clientInfo))
                { return; }
            }


            byte[] tempBuffer = new byte[1024];

            try
            {
                byte[] lengthBuffer = new byte[4];

                using (MemoryStream messageBuffer = new MemoryStream())
                {
                    while (true)
                    {
                        //  读取4字节的消息长度
                        int lengthBytesRead = 0;
                        while (lengthBytesRead < 4)
                        {
                            int read = clientInfo.Socket.Receive(
                                lengthBuffer,
                                lengthBytesRead,
                                4 - lengthBytesRead,
                                SocketFlags.None);

                            if (read == 0)
                            {
                                // 客户端断开连接
                                throw new SocketException((int)SocketError.ConnectionReset);
                            }

                            lengthBytesRead += read;
                        }

                        // 将4字节转换为消息长度(网络字节序转主机字节序)
                        int messageLength = BitConverter.ToInt32(lengthBuffer, 0);
                        messageLength = IPAddress.NetworkToHostOrder(messageLength);

                        //  根据长度读取完整消息
                        messageBuffer.SetLength(0);
                        int totalBytesRead = 0;

                        while (totalBytesRead < messageLength)
                        {
                            int bytesToRead = Math.Min(tempBuffer.Length, messageLength - totalBytesRead);
                            int read = clientInfo.Socket.Receive(tempBuffer, 0, bytesToRead, SocketFlags.None);

                            if (read == 0)
                            {
                                // 客户端断开连接
                                throw new SocketException((int)SocketError.ConnectionReset);
                            }

                            messageBuffer.Write(tempBuffer, 0, read);
                            totalBytesRead += read;
                        }

                        //  处理消息
                        string message = Encoding.UTF8.GetString(messageBuffer.ToArray());
                        clientInfo.LastActiveTime = DateTime.Now;

                        Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 客户端 {clientId} 发送: {message}");

                        // 解析客户端消息并处理
                        ProcessClientMessage(clientId, message);
                    }
                }
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode == SocketError.ConnectionReset ||
                    ex.SocketErrorCode == SocketError.ConnectionAborted)
                {
                    Console.WriteLine($"客户端 {clientId} 主动断开连接");
                }
                else if (ex.SocketErrorCode == SocketError.TimedOut)
                {
                    Console.WriteLine($"客户端 {clientId} 连接超时");
                }
                else
                {
                    Console.WriteLine($"客户端 {clientId} 网络异常: {ex.Message} (错误码: {ex.SocketErrorCode})");
                }
            }
            catch (IOException ex)
            {
                Console.WriteLine($"客户端 {clientId} IO异常: {ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"客户端 {clientId} 未知异常: {ex.Message}");
            }
            finally
            {
                // 移除客户端
                RemoveClient(clientId);
            }
        }

        /// <summary>
        /// 处理客户端发送的消息
        /// </summary>
        /// <param name="clientId">发送消息的客户端ID</param>
        /// <param name="message">JSON格式的消息字符串</param>
        private static void ProcessClientMessage(string clientId, string message)
        {
            try
            {
                // 反序列化基础消息结构
                MessageStyle clientMessage = JsonConvert.DeserializeObject<MessageStyle>(message);
                if (clientMessage == null)
                {
                    Console.WriteLine($"客户端 {clientId} 发送无效消息格式: {message}");
                    return;
                }

                // 根据消息类型处理
                switch (clientMessage.Type)
                {
                    case MessageTypeEnum.Text:
                        HandleTextMessage(clientId, clientMessage);
                        break;

                    case MessageTypeEnum.Broadcast:
                        HandleBroadcastMessage(clientId, clientMessage);
                        break;

                    case MessageTypeEnum.PrivateMsg:
                        HandlePrivateMessage(clientId, clientMessage);
                        break;

                    case MessageTypeEnum.SetUserName:
                        HandleSetUserName(clientId, clientMessage);
                        break;

                    case MessageTypeEnum.Heartbeat:
                        HandleHeartbeatMessage(clientId, clientMessage);
                        break;

                    case MessageTypeEnum.Unknown:
                        HandleUnknownMessage(clientId, clientMessage);
                        break;

                    case MessageTypeEnum.ListRequest:
                        HandleListRequest(clientId);
                        break;


                    default:
                        Console.WriteLine($"客户端 {clientId} 发送未知消息类型: {clientMessage.Type}");
                        break;
                }
            }
            catch (JsonSerializationException jsonEx)
            {
                Console.WriteLine($"客户端 {clientId} 消息反序列化失败: {jsonEx.Message},原始消息: {message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理客户端 {clientId} 消息时出错: {ex.Message}");
            }
        }

处理文本消息
        /// <summary>
        /// 处理文本消息
        /// </summary>
        private static void HandleTextMessage(string clientId, MessageStyle message)
        {
            try
            {
                StandMessageModel textModel = JsonConvert.DeserializeObject<StandMessageModel>(message.Message);
                string responseMsg = $"收到你的文本消息: {textModel.Message}";

                // 回复发送者
                MessageStyle response = new MessageStyle(MessageTypeEnum.Text, clientId,
                    JsonConvert.SerializeObject(new StandMessageModel("SERVER", clientId, responseMsg)));
                SendMessage(clientId, JsonConvert.SerializeObject(response));
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理文本消息失败: {ex.Message}");
            }
        }
处理广播消息
        /// <summary>
        /// 处理广播消息
        /// </summary>
        private static void HandleBroadcastMessage(string clientId, MessageStyle message)
        {
            try
            {
                StandMessageModel broadcastModel = JsonConvert.DeserializeObject<StandMessageModel>(message.Message);
                string broadcastContent = $"[{GetClientName(clientId)}({clientId})] 广播: {broadcastModel.Message}";

                // 构建广播消息
                MessageStyle broadcastMsg = new MessageStyle(MessageTypeEnum.Broadcast, clientId,
                    JsonConvert.SerializeObject(new StandMessageModel(clientId, "ALL", broadcastContent)));
                string broadcastJson = JsonConvert.SerializeObject(broadcastMsg);

                // 发送给所有在线客户端,包括发送者自己
                lock (_lock)
                {
                    foreach (var client in _clients)
                    {
                        SendMessage(client.Key, broadcastJson);
                    }
                }

                Console.WriteLine($"客户端 {clientId} 发送广播: {broadcastModel.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理广播消息失败: {ex.Message}");
            }
        }

处理私聊消息
        /// <summary>
        /// 处理私聊消息
        /// </summary>
        private static void HandlePrivateMessage(string clientId, MessageStyle message)
        {
            try
            {
                StandMessageModel privateModel = JsonConvert.DeserializeObject<StandMessageModel>(message.Message);
                string targetClientId = privateModel.TargetClientID;
                string privateContent = privateModel.Message;

                // 验证目标客户端是否存在
                if (!_clients.ContainsKey(targetClientId))
                {
                    // 回复发送者:目标不存在
                    string errorMsg = $"目标客户端 {targetClientId} 不存在或已离线";
                    MessageStyle errorResponse = new MessageStyle(MessageTypeEnum.Text, clientId,
                        JsonConvert.SerializeObject(new StandMessageModel("SERVER", clientId, errorMsg)));
                    SendMessage(clientId, JsonConvert.SerializeObject(errorResponse));
                    return;
                }

                // 构建私聊消息
                string senderName = GetClientName(clientId);
                string privateMsgContent = $"[{senderName}({clientId})] 私聊: {privateContent}";
                MessageStyle privateMsg = new MessageStyle(MessageTypeEnum.PrivateMsg, clientId,
                    JsonConvert.SerializeObject(new StandMessageModel(clientId, targetClientId, privateMsgContent)));

                // 发送给目标客户端
                SendMessage(targetClientId, JsonConvert.SerializeObject(privateMsg));

                // 回复发送者:发送成功
                string successMsg = $"已向 {targetClientId} 发送私聊消息: {privateContent}";
                MessageStyle successResponse = new MessageStyle(MessageTypeEnum.Text, clientId,
                    JsonConvert.SerializeObject(new StandMessageModel("SERVER", clientId, successMsg)));
                SendMessage(clientId, JsonConvert.SerializeObject(successResponse));

                Console.WriteLine($"客户端 {clientId}{targetClientId} 发送私聊: {privateContent}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理私聊消息失败: {ex.Message}");
            }
        }
处理设置用户名
        /// <summary>
        /// 处理设置用户名
        /// </summary>
        private static void HandleSetUserName(string clientId, MessageStyle message)
        {
            try
            {
                StandMessageModel userNameModel = JsonConvert.DeserializeObject<StandMessageModel>(message.Message);
                string newUserName = userNameModel.Message.Trim();

                if (string.IsNullOrEmpty(newUserName))
                {
                    // 回复错误
                    string errorMsg = "用户名不能为空";
                    MessageStyle errorResponse = new MessageStyle(MessageTypeEnum.Text, clientId,
                        JsonConvert.SerializeObject(new StandMessageModel("SERVER", clientId, errorMsg)));
                    SendMessage(clientId, JsonConvert.SerializeObject(errorResponse));
                    return;
                }

                // 更新客户端用户名
                lock (_lock)
                {
                    if (_clients.ContainsKey(clientId))
                    {
                        _clients[clientId].ClientName = newUserName;
                    }
                }

                // 回复成功
                string successMsg = newUserName;
                MessageStyle successResponse = new MessageStyle(MessageTypeEnum.SetUserName, clientId,
                    JsonConvert.SerializeObject(new StandMessageModel("SERVER", clientId, successMsg)));
                SendMessage(clientId, JsonConvert.SerializeObject(successResponse));

                Console.WriteLine($"客户端 {clientId} 设置用户名为: {newUserName}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理设置用户名失败: {ex.Message}");
            }
        }

处理心跳消息
        /// <summary>
        /// 处理心跳消息
        /// </summary>
        private static void HandleHeartbeatMessage(string clientId, MessageStyle message)
        {
            try
            {
                StandMessageModel heartbeatModel = JsonConvert.DeserializeObject<StandMessageModel>(message.Message);

                // 回复心跳确认
                string heartbeatMsg = "心跳确认 - 服务器已收到";
                MessageStyle heartbeatResponse = new MessageStyle(MessageTypeEnum.Heartbeat, clientId,
                    JsonConvert.SerializeObject(new StandMessageModel("SERVER", clientId, heartbeatMsg)));
                SendMessage(clientId, JsonConvert.SerializeObject(heartbeatResponse));

                Console.WriteLine($"客户端 {clientId} 心跳检测: {heartbeatModel.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理心跳消息失败: {ex.Message}");
            }
        }

处理未知类型消息
        /// <summary>
        /// 处理未知类型消息
        /// </summary>
        private static void HandleUnknownMessage(string clientId, MessageStyle message)
        {
            try
            {
                StandMessageModel unknownModel = JsonConvert.DeserializeObject<StandMessageModel>(message.Message);
                string responseMsg = $"收到未知类型消息: {unknownModel.Message}";

                // 回复发送者
                MessageStyle response = new MessageStyle(MessageTypeEnum.Unknown, clientId,
                    JsonConvert.SerializeObject(new StandMessageModel("SERVER", clientId, responseMsg)));
                SendMessage(clientId, JsonConvert.SerializeObject(response));
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理未知消息失败: {ex.Message}");
            }
        }
发送消息基础方法

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="clientId">目标客户端ID</param>
        /// <param name="message">JSON格式的消息字符串</param>
        private static void SendMessage(string clientId, string message)
        {
            try
            {
                ClientInfo clientInfo;
                lock (_lock)
                {
                    if (!_clients.TryGetValue(clientId, out clientInfo))
                    {
                        Console.WriteLine($"clientId:{clientId},不存在");
                        return;
                    }
                }

                // 检查Socket是否连接
                if (!clientInfo.Socket.Connected)
                {
                    Console.WriteLine($"客户端 {clientId} 已断开,跳过消息发送");
                    RemoveClient(clientId);
                    return;
                }

                // 转为 UTF-8 字节数组
                byte[] jsonBytes = Encoding.UTF8.GetBytes(message);

                // 获取长度并转换为网络字节序
                int length = jsonBytes.Length;
                int networkOrderLength = IPAddress.HostToNetworkOrder(length);
                byte[] lengthBytes = BitConverter.GetBytes(networkOrderLength);

                // 拼接长度+内容
                byte[] buffer = new byte[4 + jsonBytes.Length];
                Array.Copy(lengthBytes, 0, buffer, 0, 4);
                Array.Copy(jsonBytes, 0, buffer, 4, jsonBytes.Length);

                // 发送
                clientInfo.Socket.Send(buffer);
            }
            catch (SocketException ex)
            {
                Console.WriteLine($"向客户端 {clientId} 发送消息失败: 网络异常 {ex.SocketErrorCode} - {ex.Message}");
                RemoveClient(clientId);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"向客户端 {clientId} 发送消息失败: {ex.Message}");
            }
        }
在线用户管理

        /// <summary>
        /// 获取客户端用户名
        ///  - 无则返回ID
        /// </summary>
        private static string GetClientName(string clientId)
        {
            lock (_lock)
            {
                if (_clients.ContainsKey(clientId) && !string.IsNullOrEmpty(_clients[clientId].ClientName))
                {
                    return _clients[clientId].ClientName;
                }
                return clientId;
            }
        }

        /// <summary>
        /// 处理客户端的在线列表请求
        /// </summary>
        /// <param name="clientId">请求的客户端ID</param>
        private static void HandleListRequest(string clientId)
        {
            try
            {
                lock (_lock)
                {
                    // 构建在线列表数据
                    OnlineListResponseModel listModel = new OnlineListResponseModel
                    {
                        TotalCount = _clients.Count,
                        Users = _clients.Select(c => new OnlineUserModel
                        {
                            ClientId = c.Value.ClientId,
                            UserName = c.Value.ClientName,
                            LastActiveTime = c.Value.LastActiveTime
                        }).ToList()
                    };

                    // 构建响应消息
                    MessageStyle responseMsg = new MessageStyle(
                        MessageTypeEnum.ListRequest,
                        clientId,
                        JsonConvert.SerializeObject(listModel)
                    );

                    // 发送给请求的客户端
                    SendMessage(clientId, JsonConvert.SerializeObject(responseMsg));
                }

                Console.WriteLine($"客户端 {clientId} 请求在线列表,已返回(共{_clients.Count}个在线用户)");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理在线列表请求失败: {ex.Message}");
                // 发送错误提示给客户端
                MessageStyle errorMsg = new MessageStyle(
                    MessageTypeEnum.Text,
                    clientId,
                    JsonConvert.SerializeObject(new StandMessageModel("SERVER", clientId, "获取在线列表失败: " + ex.Message))
                );
                SendMessage(clientId, JsonConvert.SerializeObject(errorMsg));
            }
        }

命令行功能实现

        /// <summary>
        /// 处理控制台输入
        /// </summary>
        private static void HandleConsoleInput()
        {
            Console.WriteLine("\n服务器命令:");
            DeaultConsoleLine();

            while (true)
            {
                try
                {
                    string input = Console.ReadLine();
                    if (string.IsNullOrWhiteSpace(input))
                        continue;

                    var parts = input.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Length == 0) continue;

                    string command = parts[0].ToUpper();
                    string[] args = parts.Length > 1 ? parts.Skip(1).ToArray() : new string[0];

                    switch (command)
                    {
                        case "/EXIT":
                            Console.WriteLine("正在关闭服务器...");
                            Environment.Exit(0);
                            break;

                        case "/LIST":
                            Console.WriteLine("当前在线客户端:");
                            lock (_lock)
                            {
                                if (_clients.Count == 0)
                                {
                                    Console.WriteLine("  暂无客户端连接");
                                }
                                else
                                {
                                    foreach (var client in _clients)
                                    {
                                        string clientName = string.IsNullOrEmpty(client.Value.ClientName)
                                            ? "未设置" : client.Value.ClientName;
                                        Console.WriteLine($"  ID: {client.Key} | 用户名: {clientName} | 最后活跃: {client.Value.LastActiveTime:HH:mm:ss}");
                                    }
                                }
                            }
                            break;

                        case "/MSG":
                            if (args.Length >= 2)
                            {
                                string targetClientId = args[0];
                                string message = string.Join(" ", args.Skip(1));

                                // 构建服务器文本消息
                                MessageStyle serverMsg = new MessageStyle(MessageTypeEnum.Text, targetClientId,
                                    JsonConvert.SerializeObject(new StandMessageModel("SERVER", targetClientId, message)));
                                SendMessage(targetClientId, JsonConvert.SerializeObject(serverMsg));

                                Console.WriteLine($"已向 {targetClientId} 发送消息: {message}");
                            }
                            else
                            {
                                Console.WriteLine("命令格式错误,正确格式: /msg clientId message");
                            }
                            break;

                        case "/BROADCAST":
                            if (args.Length >= 1)
                            {
                                string message = string.Join(" ", args);
                                MessageStyle broadcastMsg = new MessageStyle(MessageTypeEnum.Broadcast, "SERVER",
                                    JsonConvert.SerializeObject(new StandMessageModel("SERVER", "ALL", message)));
                                string broadcastJson = JsonConvert.SerializeObject(broadcastMsg);

                                lock (_lock)
                                {
                                    foreach (var client in _clients)
                                    {
                                        SendMessage(client.Key, broadcastJson);
                                    }
                                }
                                Console.WriteLine($"已广播: {message}");
                            }
                            else
                            {
                                Console.WriteLine("命令格式错误,正确格式: /broadcast message");
                            }
                            break;

                        case "/HELP":
                            Console.WriteLine("可用命令:");
                            DeaultConsoleLine();
                            break;

                        default:
                            Console.WriteLine("未知命令,输入 /help 查看可用命令");
                            break;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"处理命令时出错: {ex.Message}");
                }
            }
        }


        /// <summary>
        /// 默认的命令行提示信息
        /// </summary>
        private static void DeaultConsoleLine()
        {
            Console.WriteLine("  /list - 查看在线客户端");
            Console.WriteLine("  /msg clientId message - 向指定客户端发送消息");
            Console.WriteLine("  /broadcast message - 广播消息");
            Console.WriteLine("  /exit - 退出服务器");
            Console.WriteLine("  /help - 查看帮助\n");
        }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值