c#Socket学习,使用Socket创建一个在线聊天,需求分析与创建项目,数据结构创建(1)

CSharp Socket学习 - 需求分析与创建项目

使用控制台实现服务端和客户端,操作使用命令实现。不使用数据库,尽量不使用第三方插件。

项目初始化

服务端项目:.NET Framework 控制台应用程序

修改项目名称和解决方案 名称

项目名称:Socket_Study_Server

解决方案名称:Socket_Study_OnClieChat

客户端项目:.NET Framework 控制台应用程序

客户端名:Socket_Study_Client

解决方案名称:Socket_Study_OnClieChat

数据结构项目:.NET Framework 类库

名称:Socket_Study_Model

解决方案名称:Socket_Study_OnClieChat

最后创建完毕

第三方引用:Newtonsoft.Json (JSON序列化库)

功能设计

客户端连接

• 客户端标识:使用GUID生成唯一客户端ID

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

• 客户端信息存储:ClientInfo类存储Socket、ID、用户名、活跃时间

csharp 复制代码
using System;
using System.Net.Sockets;

namespace Socket_Study_Pro
{
    /// <summary>
    /// 客户端信息类
    /// </summary>
    public class ClientInfo
    {
        /// <summary>
        /// 客户端id
        /// </summary>
        public string ClientId { get; set; }

        /// <summary>
        /// 客户端的用户名
        /// </summary>
        public string ClientName { get; set; }

        /// <summary>
        /// socket
        /// </summary>
        public Socket Socket { get; set; }

        /// <summary>
        /// 最后上线时间
        /// </summary>
        public DateTime LastActiveTime { get; set; }

        /// <summary>
        /// 是否链接
        /// </summary>
        public bool IsConnected { get; set; }
    }
}

• 线程安全的字典:使用锁机制管理客户端列表

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

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

• 连接状态维护:IsConnected标志位跟踪连接状态

消息协议设计

• 消息头格式:4字节长度标识 + JSON消息体,这样后期也可以发送图片或者文件,4字节长度标识可以发送4GB大小的数据

复制代码
0xFF 0xFF 0xFF 0xFF {JSON}

• 消息类型:Welcome, Text, Broadcast, PrivateMsg, SetUserName, Heartbeat, ListRequest, Unknown

csharp 复制代码
namespace Socket_Study_Entity
{
    /// <summary>
    /// 消息类型枚举
    /// </summary>
    public enum MessageTypeEnum
    {
        /// <summary>
        /// 未知类型
        /// </summary>
        Unknown = 0,

        /// <summary>
        /// 欢迎消息
        /// </summary>
        Welcome = 1,

        /// <summary>
        /// 普通文本消息
        /// </summary>
        Text = 2,

        /// <summary>
        /// 广播消息
        /// </summary>
        Broadcast = 3,

        /// <summary>
        /// 心跳消息
        /// </summary>
        Heartbeat = 4,

        /// <summary>
        /// 隐私消息
        /// </summary>
        PrivateMsg = 5,

        /// <summary>
        /// 设置自己的用户名
        /// </summary>
        SetUserName = 6,

        /// <summary>
        /// 获取用户列表
        /// </summary>
        ListRequest = 7,
    }
}

消息处理

先创建可能用到的方法,后续进行补充。

• 欢迎消息处理:连接时发送欢迎消息和客户端ID, private static void SendWelcomeMessage(string clientId)

• 文本消息处理:普通文本消息的收发 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)

• 心跳检测:保持连接活跃,检测客户端在线状态,private static void HandleHeartbeatMessage(string clientId, MessageStyle message)

• 在线列表查询:客户端可查询当前所有在线用户,private static void HandleListRequest(string clientId)

• 消息格式验证:JSON反序列化验证和异常处理,private static void HandleUnknownMessage(string clientId, MessageStyle message)

消息传输

• 消息分包处理:基于长度的消息完整接收

• 缓冲区管理:复用缓冲区减少内存分配

• 流式读取:使用MemoryStream累积消息数据

• 可靠发送:带长度信息的可靠消息发送

• 连接状态检测:发送前检查Socket连接状态

客户端会话

• 客户端心跳:通过心跳消息维持连接

• 活跃时间更新:每次消息收发更新最后活跃时间

服务器控制台

• 命令行:控制台输入命令解析

• 在线客户端列表:查看所有连接的客户端信息

• 定向消息发送:服务器向指定客户端发送消息

• 服务器广播:服务器向所有客户端广播消息

• 服务器关闭:安全关闭服务器的命令

• 帮助:显示可用命令列表

数据结构

消息模型,需要在Socket_Study_Model 中创建

• MessageStyle:消息基础结构,所有的消息都要被包裹,赋值给message字段

csharp 复制代码
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Socket_Study_Model 
{
    /// <summary>
    /// 消息基础格式
    /// </summary>
    public class MessageStyle
    {
        /// <summary>
        /// 消息类型
        /// </summary>
        [JsonConverter(typeof(StringEnumConverter))]
        public MessageTypeEnum Type { get; set; } = MessageTypeEnum.Unknown;

        /// <summary>
        /// 发送方的clientid
        /// </summary>
        public string ClientId { get; set; }

        /// <summary>
        /// 消息
        /// </summary>
        public string Message { get; set; }


        public MessageStyle(MessageTypeEnum messageTypeEnum, string clientId, string message)
        {
            Type = messageTypeEnum;
            ClientId = clientId;
            Message = message;
        }

    }
}

• StandMessageModel:标准消息模型,通用的消息模型

csharp 复制代码
using System;

namespace Socket_Study_Model
{
    /// <summary>
    /// 标准消息模型
    /// </summary>
    [Serializable]
    public class StandMessageModel
    {

        /// <summary>
        /// 发送方clientid
        /// </summary>
        public string SenderClientId;

        /// <summary>
        /// 发送方id
        /// </summary>
        public string SenderName;

        /// <summary>
        /// 目标clientid
        /// </summary>
        public string TargetClientID;

        /// <summary>
        /// 发送方名称
        /// </summary>
        public string TargetName;

        /// <summary>
        /// 消息
        /// </summary>
        public string Message;

        /// <summary>
        /// 构建消息
        /// </summary>
        /// <param name="senderClientId">发送方id</param>
        /// <param name="targetClientID">目标id</param>
        /// <param name="message">消息内容</param>
        public StandMessageModel(string senderClientId, string targetClientID, string message)
        {
            SenderClientId = senderClientId;
            TargetClientID = targetClientID;
            Message = message;
        }
    }
}

• WelComMessageModel:欢迎消息模型

csharp 复制代码
using System;

namespace Socket_Study_Entity
{
    /// <summary>
    /// 欢迎消息的model
    /// </summary>
    [Serializable]
    public class WelComMessageModel
    {
        /// <summary>
        /// 欢迎消息
        /// </summary>
        public string Message;

        public WelComMessageModel(string message)
        {
            Message = message;
        }

    }
}

• OnlineListResponseModel:在线列表响应模型,OnlineUserModel:在线用户信息模型

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Socket_Study_Model
{
    /// <summary>
    /// 在线用户信息模型
    /// </summary>
    public class OnlineUserModel
    {
        /// <summary>
        /// 客户端ID
        /// </summary>
        public string ClientId { get; set; }

        /// <summary>
        /// 用户名(未设置则显示"未命名")
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// 最后活跃时间
        /// </summary>
        public DateTime LastActiveTime { get; set; }
    }

    /// <summary>
    /// 在线列表响应模型
    /// </summary>
    public class OnlineListResponseModel
    {
        /// <summary>
        /// 在线用户总数
        /// </summary>
        public int TotalCount { get; set; }

        /// <summary>
        /// 在线用户列表
        /// </summary>
        public List<OnlineUserModel> Users { get; set; } = new List<OnlineUserModel>();
    }
}

客户端信息

• ClientInfo:包含Socket、ID、用户名、最后活跃时间、连接状态

• 线程安全存储:使用锁保护的字典存储客户端信息

网络异常处理

• Socket异常:连接重置、连接中止、超时等

• IO异常:读写操作异常

• 序列化异常:JSON格式错误处理

• 线程安全异常:并发访问控制

相关推荐
XiaoFan0127 分钟前
将有向工作流图转为结构树的实现
java·数据结构·决策树
睡一觉就好了。19 分钟前
快速排序——霍尔排序,前后指针排序,非递归排序
数据结构·算法·排序算法
齐落山大勇24 分钟前
数据结构——单链表
数据结构
丝斯20111 小时前
AI学习笔记整理(67)——大模型的Benchmark(基准测试)
人工智能·笔记·学习
whale fall1 小时前
2026 年 1-3 月雅思口语完整话题清单(1-4 月通用最终版)
笔记·学习
皮皮哎哟1 小时前
深入浅出双向链表与Linux内核链表 附数组链表核心区别解析
c语言·数据结构·内核链表·双向链表·循环链表·数组和链表的区别
xian_wwq1 小时前
【学习笔记】对网络安全“三化六防挂图作战”的理解与思考
笔记·学习·三化六防
gc_22992 小时前
C#学习调用OpenMcdf模块解析ole数据的基本用法(1)
c#·ole·openmcdf
wWYy.2 小时前
指针与引用区别
数据结构
AI视觉网奇2 小时前
metahuman 购买安装记录
笔记·学习·ue5