千家信息网

如何使用C#基于WebSocket实现聊天室功能

发表于:2025-01-17 作者:千家信息网编辑
千家信息网最后更新 2025年01月17日,这篇文章将为大家详细讲解有关如何使用C#基于WebSocket实现聊天室功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。ServerHelper:using Sy
千家信息网最后更新 2025年01月17日如何使用C#基于WebSocket实现聊天室功能

这篇文章将为大家详细讲解有关如何使用C#基于WebSocket实现聊天室功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

ServerHelper:

using System;using System.Collections;using System.Text;using System.Security.Cryptography; namespace SocketDemo{    // Server助手 负责:1 握手 2 请求转换 3 响应转换    class ServerHelper    {        ///         /// 输出连接头信息        ///         public static string ResponseHeader(string requestHeader)        {            Hashtable table = new Hashtable();             // 拆分成键值对,保存到哈希表            string[] rows = requestHeader.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);            foreach (string row in rows)            {                int splitIndex = row.IndexOf(':');                if (splitIndex > 0)                {                    table.Add(row.Substring(0, splitIndex).Trim(), row.Substring(splitIndex + 1).Trim());                }            }             StringBuilder header = new StringBuilder();            header.Append("HTTP/1.1 101 Web Socket Protocol Handshake\r\n");            header.AppendFormat("Upgrade: {0}\r\n", table.ContainsKey("Upgrade") ? table["Upgrade"].ToString() : string.Empty);            header.AppendFormat("Connection: {0}\r\n", table.ContainsKey("Connection") ? table["Connection"].ToString() : string.Empty);            header.AppendFormat("WebSocket-Origin: {0}\r\n", table.ContainsKey("Sec-WebSocket-Origin") ? table["Sec-WebSocket-Origin"].ToString() : string.Empty);            header.AppendFormat("WebSocket-Location: {0}\r\n", table.ContainsKey("Host") ? table["Host"].ToString() : string.Empty);             string key = table.ContainsKey("Sec-WebSocket-Key") ? table["Sec-WebSocket-Key"].ToString() : string.Empty;            string magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";            header.AppendFormat("Sec-WebSocket-Accept: {0}\r\n", Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + magic))));             header.Append("\r\n");             return header.ToString();        }         ///         /// 解码请求内容        ///         public static string DecodeMsg(Byte[] buffer, int len)        {            if (buffer[0] != 0x81                || (buffer[0] & 0x80) != 0x80                || (buffer[1] & 0x80) != 0x80)            {                return null;            }            Byte[] mask = new Byte[4];            int beginIndex = 0;            int payload_len = buffer[1] & 0x7F;            if (payload_len == 0x7E)            {                Array.Copy(buffer, 4, mask, 0, 4);                payload_len = payload_len & 0x00000000;                payload_len = payload_len | buffer[2];                payload_len = (payload_len << 8) | buffer[3];                beginIndex = 8;            }            else if (payload_len != 0x7F)            {                Array.Copy(buffer, 2, mask, 0, 4);                beginIndex = 6;            }             for (int i = 0; i < payload_len; i++)            {                buffer[i + beginIndex] = (byte)(buffer[i + beginIndex] ^ mask[i % 4]);            }            return Encoding.UTF8.GetString(buffer, beginIndex, payload_len);        }         ///         /// 编码响应内容        ///         public static byte[] EncodeMsg(string content)        {            byte[] bts = null;            byte[] temp = Encoding.UTF8.GetBytes(content);            if (temp.Length < 126)            {                bts = new byte[temp.Length + 2];                bts[0] = 0x81;                bts[1] = (byte)temp.Length;                Array.Copy(temp, 0, bts, 2, temp.Length);            }            else if (temp.Length < 0xFFFF)            {                bts = new byte[temp.Length + 4];                bts[0] = 0x81;                bts[1] = 126;                bts[2] = (byte)(temp.Length & 0xFF);                bts[3] = (byte)(temp.Length >> 8 & 0xFF);                Array.Copy(temp, 0, bts, 4, temp.Length);            }            else            {                byte[] st = System.Text.Encoding.UTF8.GetBytes(string.Format("暂不处理超长内容").ToCharArray());            }            return bts;        }    }}

Server:

using System;using System.Collections.Generic;using System.Text;using System.Net;using System.Net.Sockets; namespace SocketDemo{    class ClientInfo    {        public Socket Socket { get; set; }        public bool IsOpen { get; set; }        public string Address { get; set; }    }     // 管理Client    class ClientManager    {        static List clientList = new List();        public static void Add(ClientInfo info)        {            if (!IsExist(info.Address))            {                clientList.Add(info);            }        }        public static bool IsExist(string address)        {            return clientList.Exists(item => string.Compare(address, item.Address, true) == 0);        }        public static bool IsExist(string address, bool isOpen)        {            return clientList.Exists(item => string.Compare(address, item.Address, true) == 0 && item.IsOpen == isOpen);        }        public static void Open(string address)        {            clientList.ForEach(item =>            {                if (string.Compare(address, item.Address, true) == 0)                {                    item.IsOpen = true;                }            });        }        public static void Close(string address = null)        {            clientList.ForEach(item =>            {                if (address == null || string.Compare(address, item.Address, true) == 0)                {                    item.IsOpen = false;                    item.Socket.Shutdown(SocketShutdown.Both);                }            });        }        // 发送消息到ClientList        public static void SendMsgToClientList(string msg, string address = null)        {            clientList.ForEach(item =>            {                if (item.IsOpen && (address == null || item.Address != address))                {                    SendMsgToClient(item.Socket, msg);                }            });        }        public static void SendMsgToClient(Socket client, string msg)        {            byte[] bt = ServerHelper.EncodeMsg(msg);            client.BeginSend(bt, 0, bt.Length, SocketFlags.None, new AsyncCallback(SendTarget), client);        }        private static void SendTarget(IAsyncResult res)        {            //Socket client = (Socket)res.AsyncState;            //int size = client.EndSend(res);        }    }     // 接收消息    class ReceiveHelper    {        public byte[] Bytes { get; set; }        public void ReceiveTarget(IAsyncResult res)        {            Socket client = (Socket)res.AsyncState;            int size = client.EndReceive(res);            if (size > 0)            {                string address = client.RemoteEndPoint.ToString(); // 获取Client的IP和端口                string stringdata = null;                if (ClientManager.IsExist(address, false)) // 握手                {                    stringdata = Encoding.UTF8.GetString(Bytes, 0, size);                    ClientManager.SendMsgToClient(client, ServerHelper.ResponseHeader(stringdata));                    ClientManager.Open(address);                }                else                {                    stringdata = ServerHelper.DecodeMsg(Bytes, size);                }                if (stringdata.IndexOf("exit") > -1)                {                    ClientManager.SendMsgToClientList(address + "已从服务器断开", address);                    ClientManager.Close(address);                    Console.WriteLine(address + "已从服务器断开");                    Console.WriteLine(address + " " + DateTimeOffset.Now.ToString("G"));                    return;                }                else                {                    Console.WriteLine(stringdata);                    Console.WriteLine(address + " " + DateTimeOffset.Now.ToString("G"));                    ClientManager.SendMsgToClientList(stringdata, address);                }            }            // 继续等待            client.BeginReceive(Bytes, 0, Bytes.Length, SocketFlags.None, new AsyncCallback(ReceiveTarget), client);        }    }     // 监听请求    class AcceptHelper    {        public byte[] Bytes { get; set; }         public void AcceptTarget(IAsyncResult res)        {            Socket server = (Socket)res.AsyncState;            Socket client = server.EndAccept(res);            string address = client.RemoteEndPoint.ToString();             ClientManager.Add(new ClientInfo() { Socket = client, Address = address, IsOpen = false });            ReceiveHelper rs = new ReceiveHelper() { Bytes = this.Bytes };            IAsyncResult recres = client.BeginReceive(rs.Bytes, 0, rs.Bytes.Length, SocketFlags.None, new AsyncCallback(rs.ReceiveTarget), client);            // 继续监听            server.BeginAccept(new AsyncCallback(AcceptTarget), server);        }    }     class Program    {        static void Main(string[] args)        {            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            server.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 200)); // 绑定IP+端口            server.Listen(10); // 开始监听             Console.WriteLine("等待连接...");             AcceptHelper ca = new AcceptHelper() { Bytes = new byte[2048] };            IAsyncResult res = server.BeginAccept(new AsyncCallback(ca.AcceptTarget), server);             string str = string.Empty;            while (str != "exit")            {                str = Console.ReadLine();                Console.WriteLine("ME: " + DateTimeOffset.Now.ToString("G"));                ClientManager.SendMsgToClientList(str);            }            ClientManager.Close();            server.Close();        }    }}

Client:

        

关于"如何使用C#基于WebSocket实现聊天室功能"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

内容 篇文章 监听 功能 聊天室 C# 更多 服务器 消息 端口 服务 不错 实用 信息 助手 文章 知识 编码 哈希 连接头 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络技术面试常规问题 北京服务器电源价位 网络安全数字货币股 绝地求生上为啥一直服务器繁忙 行业志专辑数据库产品不支持 腾讯云服务器市场份额 青岛云灯网络技术有限公司 mysql数据库的组件 网络安全本科专业全称 乌镇互联网大会绿盟科技 地灵曲游戏关闭服务器 东城区网络技术咨询职责 苏州平江区网络技术公司地址 银河麒麟服务器操作系统中标价 ActiveMQ里的数据库 服务器游戏怎么删除 摄像头设置不到服务器 高端网络安全建设找哪家 河南省网络安全法规 路由器怎么设置虚拟服务器 锐捷宽带服务器名称怎么设置 数据库中NULL如何处理 nginx网络服务器负载均衡 军营网络安全宣传周大讨论 服务器安全狗设置备份 互联网巨头科技股 网络安全运营技术试卷答案 网络安全之远离不良信息 广州和深圳软件开发工资对比 软件开发和软件编程
0