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 消息体" 协议发送给客户端,完成客户端身份初始化。

    启动客户端消息处理线程

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

为当前客户端分配独立的 private static void HandleClient(string clientId) 线程。

  1. 然后接收和处理客户端发来的消息 ProcessClientMessage(clientId, message);

  2. 解析数据,先读取四字节长度的消息,然后一直接收并解析数据

csharp 复制代码
          //  读取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. 处理各种消息
csharp 复制代码
        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. 使用控制台发送命令
csharp 复制代码
        /// <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这一个工具代码,只有一个地方使用到了,所以也可以删掉直接写到用地方。

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

变量创建

csharp 复制代码
        /// <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链接

csharp 复制代码
        /// <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中调用

csharp 复制代码
        static void Main(string[] args)
        {
            EventRegistration();
            InitSocket();
        }

事件处理

用户管理

发送欢迎消息,在用户连接之后
csharp 复制代码
        /// <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} 已从列表中移除");
                }
            }
        }

消息事件

消息接收与消息预处理
csharp 复制代码
        /// <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}");
            }
        }
处理文本消息
csharp 复制代码
        /// <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}");
            }
        }
处理广播消息
csharp 复制代码
        /// <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}");
            }
        }
处理私聊消息
csharp 复制代码
        /// <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}");
            }
        }
处理设置用户名
csharp 复制代码
        /// <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}");
            }
        }
处理心跳消息
csharp 复制代码
        /// <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}");
            }
        }
处理未知类型消息
csharp 复制代码
        /// <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}");
            }
        }
发送消息基础方法
csharp 复制代码
        /// <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}");
            }
        }
在线用户管理
csharp 复制代码
        /// <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));
            }
        }

命令行功能实现

csharp 复制代码
        /// <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");
        }
相关推荐
Heart_to_Yang3 小时前
企业惠普打印机添加、打印乱码与扫描失败故障通用排查手册
运维·服务器·经验分享
xwz小王子4 小时前
IROS 2025论文分享:基于大语言模型与行为树的人机交互学习实现自适应机器人操作
学习·语言模型·人机交互
嵌入式×边缘AI:打怪升级日志4 小时前
USB协议详解:从物理连接到数据传输的完整解析
网络·学习·usb
superman超哥4 小时前
仓颉热点代码识别深度解析
开发语言·后端·python·c#·仓颉
W.KN4 小时前
关于论文如何开始的学习笔记
人工智能·笔记·学习
坚定信念,勇往无前4 小时前
Alibaba Cloud Linux 4.0安装mongodump
linux·运维·服务器
Lv11770084 小时前
Visual Studio中的接口
ide·笔记·c#·visual studio
qq_310658514 小时前
janux源码走读(五)Janus事件处理模块(events/)
服务器·c++·音视频
虹梦未来4 小时前
【运维心得】Ubuntu2404编译nginx隐藏Server信息
运维·服务器·nginx