c#Socket学习,使用Socket创建一个在线聊天,客户端代码实现(4)

客户端代码

技术点

  • 传输方式:TCP 协议,长度前缀(4 byte Big-Endian)+ UTF-8 JSON 解决粘包/半包。
  • 异步接收:独立后台线程 ReceiveServerMessages 持续阻塞接收。
  • 心跳机制:可手动 /heartbeat 或未来定时发送,服务器回 pong 确认存活。
  • 消息路由:统一入口 ProcessServerMessage MessageTypeEnum分发到对应 Handle*Message 方法。
  • 断线自退出:接收线程检测到 SocketError.ConnectionResetread==0 时,自动 Environment.Exit(0),防止僵尸进程。
  • 用户友好命令行:使用命令行发送消息和设置自己的信息

项目流程

  1. 入口
    设置控制台标题 → 注册进程退出事件 →InitializeClient()发起 TCP 连接。
  2. 连接
    启动后台线程 ReceiveServerMessages 循环解析“长度头+JSON”数据。
    主线程进入 HandleConsoleInput 阻塞等待用户命令。
  3. 收发
    接收线程:收到完整一帧 →ProcessServerMessage→ 控制台彩色输出。
    发送线程:用户键入命令 → 构造 MessageStyleSendMessageToServer → 拼接长度头 → Socket.Send
  4. 退出
    用户/exitCtrl-C ProcessExit 事件 Shutdown/Close Socket → 接收线程退出 → 进程结束。

代码

初始化 & 连接


        /// <summary>
        /// 客户端Socket
        /// </summary>
        private static Socket _clientSocket;

        /// <summary>
        /// 服务器IP
        /// </summary>
        private static string _serverIp = "127.0.0.1";

        /// <summary>
        /// 服务器端口
        /// </summary>
        private static int _serverPort = 23841;

        /// <summary>
        /// 客户端ID
        /// </summary>
        private static string _clientId;

        /// <summary>
        /// 自己的用户名
        /// </summary>
        private static string _clientUserName;

        private static void Main(string[] args)
        {
            Console.Title = "Socket客户端";

            RegisterApplicationExitEvent();


            if (InitializeClient() == true)
            {
                // 控制台交互
                HandleConsoleInput();
            }


            Console.WriteLine("按任意键退出...");
            Console.ReadKey();
        }

        /// <summary>
        /// 初始化socket客户端
        /// </summary>
        /// <returns></returns>
        private static bool InitializeClient()
        {
            try
            {
                // 初始化Socket
                _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // 连接服务器
                Console.Write($"正在连接服务器 {_serverIp}:{_serverPort}...");
                _clientSocket.Connect(new IPEndPoint(IPAddress.Parse(_serverIp), _serverPort));
                Console.WriteLine("连接成功!");

                // 启动接收服务器消息的线程
                Thread receiveThread = new Thread(ReceiveServerMessages);
                receiveThread.IsBackground = true;
                receiveThread.Start();
                return true;
            }
            catch (SocketException ex)
            {
                Console.WriteLine($"\n连接服务器失败: {ex.SocketErrorCode} - {ex.Message}");
                Console.WriteLine("请检查服务器是否启动,或IP/端口是否正确");
                return false;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"\n客户端启动失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 接收服务器消息的线程
        /// </summary>
        private static void ReceiveServerMessages()
        {
            // 复用缓冲区,避免重复创建
            byte[] tempBuffer = new byte[1024];
            byte[] lengthBuffer = new byte[4];

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

                            if (read == 0)
                            {
                                throw new SocketException((int) SocketError.ConnectionReset);
                            }

                            lengthBytesRead += read;
                        }

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

                        // 2. 读取完整消息内容
                        messageBuffer.SetLength(0);
                        int totalBytesRead = 0;

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

                            if (read == 0)
                            {
                                throw new SocketException((int) SocketError.ConnectionReset);
                            }

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

                        // 3. 解析消息
                        string message = Encoding.UTF8.GetString(messageBuffer.ToArray());
                        ProcessServerMessage(message);
                    }
                }
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode == SocketError.ConnectionReset ||
                    ex.SocketErrorCode == SocketError.ConnectionAborted)
                {
                    Console.WriteLine($"\n[服务器] 连接已断开");
                }
                else
                {
                    Console.WriteLine($"\n[错误] 接收消息失败: {ex.SocketErrorCode} - {ex.Message}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"\n[错误] 接收消息失败: {ex.Message}");
            }
            finally
            {
                // 断开连接后退出控制台输入循环
                Environment.Exit(0);
            }
        }

消息接收


        /// <summary>
        /// 处理服务器发送的消息
        /// </summary>
        /// <param name="message">服务器消息(JSON字符串)</param>
        private static void ProcessServerMessage(string message)
        {
            // 空消息直接忽略
            if (string.IsNullOrWhiteSpace(message))
            {
                Console.WriteLine("\n[服务器] 收到空消息");
                return;
            }

            try
            {
                // 反序列化基础消息结构
                MessageStyle serverMessage = JsonConvert.DeserializeObject<MessageStyle>(message);

                // 消息结构验证
                if (serverMessage == null)
                {
                    Console.WriteLine($"\n[服务器] 收到无效的消息格式: {message}");
                    return;
                }

                // 根据消息类型处理不同逻辑
                HandleMessageByType(serverMessage);
            }
            catch (JsonSerializationException jsonEx)
            {
                // JSON反序列化失败(非标准MessageStyle格式)
                Console.WriteLine($"\n[服务器] 收到非标准JSON消息: {message}");
                Console.WriteLine($"[反序列化错误] {jsonEx.Message}");
            }
            catch (Exception ex)
            {
                // 其他异常
                Console.WriteLine($"\n[服务器] 处理消息时发生错误: {ex.Message}");
                Console.WriteLine($"[原始消息] {message}");
            }
        }
      ```
      
      
      ```csharp
        /// <summary>
        /// 按消息类型处理服务器消息
        /// </summary>
        /// <param name="serverMessage">解析后的消息对象</param>
        private static void HandleMessageByType(MessageStyle serverMessage)
        {
            switch (serverMessage.Type)
            {
                case MessageTypeEnum.Welcome:
                    HandleWelcomeMessage(serverMessage);
                    break;

                case MessageTypeEnum.Text:
                    Console.WriteLine($"\n[服务器文本] {serverMessage.Message}");
                    break;

                case MessageTypeEnum.Broadcast:
                    Console.WriteLine($"\n[服务器广播] {serverMessage.Message}");
                    break;

                case MessageTypeEnum.Heartbeat:
                    Console.WriteLine($"\n[服务器心跳] {serverMessage.Message}");
                    break;

                case MessageTypeEnum.Unknown:
                    Console.WriteLine($"\n[服务器未知类型消息] {serverMessage.Message}");
                    break;

                case MessageTypeEnum.PrivateMsg:
                    HandlePrivateMessage(serverMessage);
                    break;

                case MessageTypeEnum.SetUserName:
                    HandleSetUserNameMessage(serverMessage);
                    break;

                case MessageTypeEnum.ListRequest:
                    HandleOnlineListResponse(serverMessage);
                    break;

                default:
                    Console.WriteLine($"\n[服务器未定义消息类型] 类型: {serverMessage.Type}, 内容: {serverMessage.Message}");
                    break;
            }
        }

处理欢迎消息

        /// <summary>
        /// 处理欢迎消息
        /// </summary>
        /// <param name="serverMessage">服务器消息对象</param>
        private static void HandleWelcomeMessage(MessageStyle serverMessage)
        {
            try
            {
                // 记录客户端ID
                if (!string.IsNullOrWhiteSpace(serverMessage.ClientId))
                {
                    _clientId = serverMessage.ClientId;
                }

                // 解析欢迎消息内容
                WelComMessageModel welcomeContent =
                    JsonConvert.DeserializeObject<WelComMessageModel>(serverMessage.Message);

                Console.WriteLine($"\n[服务器欢迎] {welcomeContent?.Message ?? "欢迎连接服务器"}");
                Console.WriteLine($"[客户端ID] {_clientId}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"\n[服务器] 欢迎消息解析失败: {ex.Message}");
                Console.WriteLine($"[原始欢迎消息] {serverMessage.Message}");
            }
        }

处理私信消息
        /// <summary>
        /// 处理私聊消息
        /// </summary>
        /// <param name="serverMessage">服务器消息对象</param>
        private static void HandlePrivateMessage(MessageStyle serverMessage)
        {
            try
            {
                StandMessageModel privateMsg = JsonConvert.DeserializeObject<StandMessageModel>(serverMessage.Message);

                string senderName = string.IsNullOrWhiteSpace(privateMsg.SenderClientId)
                    ? privateMsg.SenderClientId
                    : $"{privateMsg.SenderName ?? "未知用户"}({privateMsg.SenderClientId})";

                Console.WriteLine($"\n[私聊消息] 来自 {senderName}: {privateMsg.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"\n[服务器] 私聊消息解析失败: {ex.Message}");
                Console.WriteLine($"[原始私聊消息] {serverMessage.Message}");
            }
        }
处理设置用户名相关消息
        /// <summary>
        /// 处理设置用户名相关消息
        /// </summary>
        /// <param name="serverMessage">服务器消息对象</param>
        private static void HandleSetUserNameMessage(MessageStyle serverMessage)
        {
            try
            {
                StandMessageModel userNameMsg = JsonConvert.DeserializeObject<StandMessageModel>(serverMessage.Message);
                _clientUserName = userNameMsg.Message;

                Console.WriteLine($"\n[服务器] 用户名设置成功: {_clientUserName}");
                Console.WriteLine($"[当前信息] ID:{_clientId}, 用户名:{_clientUserName}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"\n[服务器] 用户名消息解析失败: {ex.Message}");
                Console.WriteLine($"[原始用户名消息] {serverMessage.Message}");
            }
        }
处理服务器返回的在线列表消息
        /// <summary>
        /// 处理服务器返回的在线列表消息
        /// </summary>
        /// <param name="serverMessage">服务器消息对象</param>
        private static void HandleOnlineListResponse(MessageStyle serverMessage)
        {
            try
            {
                OnlineListResponseModel listModel =
                    JsonConvert.DeserializeObject<OnlineListResponseModel>(serverMessage.Message);
                if (listModel == null || listModel.Users == null)
                {
                    Console.WriteLine("\n[服务器] 在线列表数据格式错误");
                    return;
                }

                Console.WriteLine("\n===== 当前在线用户列表 =====");
                Console.WriteLine($"总在线人数: {listModel.TotalCount}");
                if (listModel.Users.Count == 0)
                {
                    Console.WriteLine("  暂无在线用户");
                }
                else
                {
                    for (int i = 0; i < listModel.Users.Count; i++)
                    {
                        var user = listModel.Users[i];
                        string userName = string.IsNullOrWhiteSpace(user.UserName) ? "未命名" : user.UserName;
                        string activeTime = user.LastActiveTime.ToString("HH:mm:ss");
                        Console.WriteLine($"  [{i + 1}] ID: {user.ClientId} | 用户名: {userName} | 最后活跃: {activeTime}");
                    }
                }

                Console.WriteLine("===========================\n");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"\n[服务器] 解析在线列表失败: {ex.Message}");
                Console.WriteLine($"[原始消息] {serverMessage.Message}");
            }
        }
        

发送消息

        /// <summary>
        /// 发送消息到服务器,最基础的方法
        /// </summary>
        /// <param name="message">JSON格式的完整消息</param>      
        private static void SendMessageToServer(string message)
        {
            if (_clientSocket == null || !_clientSocket.Connected)
            {
                Console.WriteLine("未连接到服务器,无法发送消息");
                return;
            }

            try
            {
                // 转为UTF8字节数组
                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);

                // 发送
                _clientSocket.Send(buffer);
            }
            catch (SocketException ex)
            {
                Console.WriteLine($"[发送失败] 网络异常: {ex.SocketErrorCode} - {ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[发送失败] {ex.Message}");
            }
        }
发送消息,传入消息类型,消息的json

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="messageType">消息类型</param>
        /// <param name="message">消息内容</param>      
        private static void SendMessage(MessageTypeEnum messageType, string message)
        {
            string jsonMessage = "";

            switch (messageType)
            {
                case MessageTypeEnum.Unknown:
                    StandMessageModel unknownModel = new StandMessageModel(_clientId, _clientId, message);
                    jsonMessage = JsonConvert.SerializeObject(unknownModel);
                    MessageStyle unknownStyle = new MessageStyle(_clientId, jsonMessage, messageType);
                    SendMessageToServer(JsonConvert.SerializeObject(unknownStyle));
                    break;

                case MessageTypeEnum.Welcome:
                    Console.WriteLine("不能发送欢迎消息,只能让服务器发送");
                    break;

                case MessageTypeEnum.Text:
                    StandMessageModel textModel = new StandMessageModel(_clientId, _clientId, message);
                    jsonMessage = JsonConvert.SerializeObject(textModel);
                    MessageStyle textStyle = new MessageStyle(_clientId, jsonMessage, messageType);
                    SendMessageToServer(JsonConvert.SerializeObject(textStyle));
                    Console.WriteLine($"[已发送文本] {message}");
                    break;

                case MessageTypeEnum.Broadcast:
                    MessageStyle broadcastStyle = new MessageStyle(_clientId, message, messageType);
                    SendMessageToServer(JsonConvert.SerializeObject(broadcastStyle));
                    break;

                case MessageTypeEnum.Heartbeat:
                    StandMessageModel heartbeatModel = new StandMessageModel(_clientId, _clientId, message);
                    jsonMessage = JsonConvert.SerializeObject(heartbeatModel);
                    MessageStyle heartbeatStyle = new MessageStyle(_clientId, jsonMessage, messageType);
                    SendMessageToServer(JsonConvert.SerializeObject(heartbeatStyle));
                    break;

                case MessageTypeEnum.SetUserName:
                    StandMessageModel setUserNameModel = new StandMessageModel(_clientId, _clientId, message);
                    jsonMessage = JsonConvert.SerializeObject(setUserNameModel);
                    MessageStyle setUserNameStyle = new MessageStyle(_clientId, jsonMessage, messageType);
                    SendMessageToServer(JsonConvert.SerializeObject(setUserNameStyle));
                    break;

                case MessageTypeEnum.ListRequest:
                    StandMessageModel listRequestModel = new StandMessageModel(_clientId, _clientId, message);
                    jsonMessage = JsonConvert.SerializeObject(listRequestModel);
                    MessageStyle listRequestStyle = new MessageStyle(_clientId, jsonMessage, messageType);
                    SendMessageToServer(JsonConvert.SerializeObject(listRequestStyle));
                    break;

                case MessageTypeEnum.PrivateMsg:
                    // 这里需要目标ID,应该用 SendPrivateMsg 方法
                    Console.WriteLine("[错误] 请使用 SendPrivateMsg 方法发送私聊消息");
                    break;

                default:
                    Console.WriteLine($"[错误] 不支持的消息类型: {messageType}");
                    break;
            }
        }
  
发送私聊消息
     /// <summary>
        /// 发送私聊消息
        /// </summary>
        /// <param name="targetId">目标客户端ID</param>
        /// <param name="message">消息内容</param>
        private static void SendPrivateMsg(string targetId, string message)
        {
            StandMessageModel standMessageModel = new StandMessageModel(_clientId, targetId, message);
            string msgContent = JsonConvert.SerializeObject(standMessageModel);
            MessageStyle messageStyle = new MessageStyle(_clientId, msgContent, MessageTypeEnum.PrivateMsg);
            // 发送消息到服务器
            SendMessageToServer(JsonConvert.SerializeObject(messageStyle));
        }

控制台命令

        /// <summary>
        /// 处理控制台输入
        /// </summary>
        private static void HandleConsoleInput()
        {
            Console.WriteLine("\n===== 客户端命令 =====");
            DefaultConsoleLine();
            Console.WriteLine("======================\n");

            while (true)
            {
                try
                {
                    Console.Write("> ");
                    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 "/MYID":
                            if (string.IsNullOrEmpty(_clientId))
                            {
                                Console.WriteLine("[提示] 尚未收到服务器分配的客户端ID");
                            }
                            else
                            {
                                Console.WriteLine($"[我的客户端ID] {_clientId}");
                            }

                            break;

                        case "/GETNAME":
                            if (string.IsNullOrEmpty(_clientUserName))
                            {
                                Console.WriteLine("[提示] 尚未设置用户名,请使用 /setname 用户名 命令设置");
                            }
                            else
                            {
                                Console.WriteLine($"[我的用户名] {_clientUserName}");
                            }

                            break;

                        case "/SETNAME":
                            if (args.Length >= 1)
                            {
                                string newName = string.Join(" ", args);
                                SendMessage(MessageTypeEnum.SetUserName, newName);
                                Console.WriteLine($"[提示] 正在设置用户名为: {newName}");
                            }
                            else
                            {
                                Console.WriteLine("命令格式错误,正确格式: /setname 你的用户名");
                            }

                            break;

                        case "/SEND":
                            if (args.Length >= 1)
                            {
                                string message = string.Join(" ", args);
                                SendMessage(MessageTypeEnum.Text, message);
                            }
                            else
                            {
                                Console.WriteLine("命令格式错误,正确格式: /send 消息内容");
                            }

                            break;

                        case "/TEXT":
                            if (args.Length >= 1)
                            {
                                string message = string.Join(" ", args);
                                SendMessage(MessageTypeEnum.Text, message);
                            }
                            else
                            {
                                Console.WriteLine("命令格式错误,正确格式: /text 消息内容");
                            }

                            break;

                        case "/BROADCAST":
                            if (args.Length >= 1)
                            {
                                // 解析广播类型(第一个参数如果是枚举值,则识别为类型,否则默认UserMessage)
                                BroadcastMessageType broadcastType = BroadcastMessageType.UserMessage;
                                string messageContent = string.Empty;

                                // 检查第一个参数是否为有效的广播类型
                                if (Enum.TryParse<BroadcastMessageType>(args[0], true, out var parsedType))
                                {
                                    broadcastType = parsedType;
                                    // 消息内容为剩余参数拼接
                                    messageContent = args.Length > 1 ? string.Join(" ", args.Skip(1)) : string.Empty;
                                }
                                else
                                {
                                    // 未指定类型,全部参数作为消息内容
                                    messageContent = string.Join(" ", args);
                                }

                                if (string.IsNullOrWhiteSpace(messageContent))
                                {
                                    Console.WriteLine("广播消息内容不能为空!");
                                    break;
                                }

                                BroadcastMessageModel broadcastModel = new BroadcastMessageModel(
                                    message: messageContent,
                                    senderClientId: _clientId,
                                    messageType: broadcastType
                                );

                                // 发送消息
                                SendMessage(MessageTypeEnum.Broadcast, JsonConvert.SerializeObject(broadcastModel));
                                Console.WriteLine($"[已发送{broadcastType}类型广播] {messageContent}");
                            }
                            else
                            {
                                Console.WriteLine("命令格式错误,正确格式:");
                                Console.WriteLine("  /broadcast [消息类型] 消息内容 (例:/broadcast Warning 服务器即将重启)");
                                Console.WriteLine("  /broadcast 消息内容 (默认:UserMessage类型)");
                                Console.WriteLine("  支持的类型:UserMessage/Warning/Error/StatusUpdate");
                            }

                            break;

                        case "/HEARTBEAT":
                            if (args.Length >= 1)
                            {
                                string message = string.Join(" ", args);
                                SendMessage(MessageTypeEnum.Heartbeat, message);
                                Console.WriteLine($"[已发送心跳] {message}");
                            }
                            else
                            {
                                // 如果没有参数,发送默认心跳消息
                                SendMessage(MessageTypeEnum.Heartbeat, "online");
                                Console.WriteLine("[已发送心跳] online");
                            }

                            break;

                        case "/CUSTOM":
                            if (args.Length >= 1)
                            {
                                string message = string.Join(" ", args);
                                SendMessage(MessageTypeEnum.Unknown, message);
                                Console.WriteLine($"[已发送自定义消息] {message}");
                            }
                            else
                            {
                                Console.WriteLine("命令格式错误,正确格式: /custom 消息内容");
                            }

                            break;

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

                                SendPrivateMsg(targetClientId, message);
                                Console.WriteLine($"[私聊给 {targetClientId}] {message}");
                            }
                            else
                            {
                                Console.WriteLine("命令格式错误,正确格式: /msgto 目标客户端ID 消息内容");
                            }

                            break;

                        case "/LIST":
                            // 发送在线列表请求
                            SendMessage(MessageTypeEnum.ListRequest, "request_online_list");
                            Console.WriteLine("[提示] 正在请求在线用户列表...");
                            break;

                        case "/HELP":
                            Console.WriteLine("\n===== 客户端命令帮助 =====");
                            DefaultConsoleLine();
                            Console.WriteLine("===========================\n");
                            break;

                        default:
                            // 如果不是以/开头的命令,直接作为文本消息发送
                            if (!input.StartsWith("/"))
                            {
                                SendMessage(MessageTypeEnum.Text, input);
                            }
                            else
                            {
                                Console.WriteLine("未知命令,输入 /help 查看可用命令");
                            }

                            break;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[错误] 处理输入失败: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 默认的控制台提示信息
        /// </summary>
        private static void DefaultConsoleLine()
        {
            Console.WriteLine("  直接输入 - 发送文本消息");
            Console.WriteLine("  /myid - 查看自己的客户端ID");
            Console.WriteLine("  /getname - 获取自己的名字");
            Console.WriteLine("  /setname 用户名 - 设置自己的名字");
            Console.WriteLine("  /send 消息内容 - 发送消息到服务器");
            Console.WriteLine("  /text 消息内容 - 发送文本消息(默认类型)");
            Console.WriteLine("  /broadcast 消息内容 - 发送广播消息(所有客户端可见,包括自己)");
            Console.WriteLine("  /heartbeat 消息内容 - 发送心跳消息");
            Console.WriteLine("  /custom 消息内容 - 发送自定义类型消息");
            Console.WriteLine("  /msgto 目标ID 消息 - 发送私聊消息到指定客户端");
            Console.WriteLine("  /list - 查看当前在线用户列表");
            Console.WriteLine("  /help - 查看帮助");
            Console.WriteLine("  /exit - 退出客户端");
        }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值