广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C#基于WebSocket实现聊天室功能
  • 794
分享到

C#基于WebSocket实现聊天室功能

2024-04-02 19:04:59 794人浏览 独家记忆
摘要

本文实例为大家分享了C#基于websocket实现聊天室功能的具体代码,供大家参考,具体内容如下 前面两篇温习了,C# Socket内容 本章根据Socket异步聊天室修改成WEBS

本文实例为大家分享了C#基于websocket实现聊天室功能的具体代码,供大家参考,具体内容如下

前面两篇温习了,C# Socket内容

本章根据Socket异步聊天室修改成WEBSocket聊天室

WebSocket特别的地方是 握手和消息内容的编码、解码(添加了ServerHelper协助处理)

ServerHelper:

using System;
using System.Collections;
using System.Text;
using System.Security.Cryptography;
 
namespace SocketDemo
{
    // Server助手 负责:1 握手 2 请求转换 3 响应转换
    class ServerHelper
    {
        /// <summary>
        /// 输出连接头信息
        /// </summary>
        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();
        }
 
        /// <summary>
        /// 解码请求内容
        /// </summary>
        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);
        }
 
        /// <summary>
        /// 编码响应内容
        /// </summary>
        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<ClientInfo> clientList = new List<ClientInfo>();
        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:

<!DOCTYPE html>
<script>
    var mySocket;
    function Star() {
        mySocket = new WebSocket("ws://127.0.0.1:200", "my-custom-protocol");
        mySocket.onopen = function Open() {
            Show("连接打开");
        };
        mySocket.onmessage = function (evt) {
            Show(evt.data);
        };
        mySocket.onclose = function Close() {
            Show("连接关闭");
            mySocket.close();
        };
    }
    function Send() {
        var content = document.getElementById("content").value;
        Show(content);
        mySocket.send(content);
    }
    function Show(msg) {
        var roomContent = document.getElementById("roomContent");
        roomContent.innerHTML = msg + "<br/>" + roomContent.innerHTML;
    }
</script>
<html>
<head>
    <title></title>
</head>
<body>
    <div id="roomContent" style="width: 500px; height: 200px; overflow: hidden; border: 2px solid #686868;
        margin-bottom: 10px; padding: 10px 0px 0px 10px;">
    </div>
    <div>
        <textarea id="content" cols="50" rows="3" style="padding: 10px 0px 0px 10px;"></textarea>
    </div>
    <input type="button" value="Connection" οnclick="Star()" />
    <input type="button" value="Send" οnclick="Send()" />
</body>
</html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: C#基于WebSocket实现聊天室功能

本文链接: https://www.lsjlt.com/news/138957.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C#基于WebSocket实现聊天室功能
    本文实例为大家分享了C#基于WebSocket实现聊天室功能的具体代码,供大家参考,具体内容如下 前面两篇温习了,C# Socket内容 本章根据Socket异步聊天室修改成WebS...
    99+
    2022-11-13
  • 如何使用C#基于WebSocket实现聊天室功能
    这篇文章将为大家详细讲解有关如何使用C#基于WebSocket实现聊天室功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。ServerHelper:using System;using ...
    99+
    2023-06-29
  • 基于C++实现TCP聊天室功能
    本文实例为大家分享了C++实现TCP聊天室功能的具体代码,供大家参考,具体内容如下 TCPServer.cpp: // TCPServer.cpp : Defines the ...
    99+
    2022-11-12
  • C#使用WebSocket实现聊天室功能
    WebSocket介绍 WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 在WebSocket API中,浏览器和服务器只需要做一个握手的动作...
    99+
    2022-11-13
  • C#基于Socket实现简单聊天室功能
    因为这段时间在学习Socket,所以就试着写了一个简单的聊天室。主要分为服务器端和多个客户端。利用服务器端作数据中转站,实现消息群发。 1、服务器端有两个类: using Syste...
    99+
    2022-11-13
  • C++基于socket编程实现聊天室功能
    本文实例为大家分享了C++基于socket编程实现聊天室的具体代码,供大家参考,具体内容如下 服务端 // server.cpp : 此文件包含 "main" 函数。程序执行将在...
    99+
    2022-11-12
  • 基于UDP实现聊天室功能
    本文实例为大家分享了UDP实现聊天室功能的具体代码,供大家参考,具体内容如下 项目结构 data.java package udp; import java.net.Inet...
    99+
    2022-11-12
  • Java基于NIO实现聊天室功能
    本文实例为大家分享了Java基于NIO实现聊天室功能的具体代码,供大家参考,具体内容如下 Sever端 package com.qst.one; import java.io....
    99+
    2022-11-12
  • 基于websocket实现简单聊天室对话
    本文实例为大家分享了websocket实现简单聊天室对话的具体代码,供大家参考,具体内容如下 首先搭建一个node的环境,在app.js中写入以下代码 npm install s...
    99+
    2022-11-12
  • 基于websocket如何实现聊天室对话
    这篇文章主要介绍了基于websocket如何实现聊天室对话,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。具体内容如下首先搭建一个node的环境,在app.js中写入以下代码n...
    99+
    2023-06-20
  • 基于websocket的聊天功能怎么实现
    本篇内容主要讲解“基于websocket的聊天功能怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“基于websocket的聊天功能怎么实现”吧!   一...
    99+
    2022-10-19
  • Java基于NIO怎么实现聊天室功能
    Java基于NIO怎么实现聊天室功能,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Sever端package com.qst.one;import java...
    99+
    2023-06-21
  • C++基于socket UDP网络编程实现简单聊天室功能
    本文实例为大家分享了C++基于socket UDP实现简单聊天室功能的具体代码,供大家参考,具体内容如下 0.通信步骤流程图 (左:服务器;右:客户端;) 1.服务器代码 1.1服...
    99+
    2022-11-12
  • C++基于socket UDP网络编程如何实现聊天室功能
    这篇文章主要介绍C++基于socket UDP网络编程如何实现聊天室功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体内容如下0.通信步骤流程图(左:服务器;右:客户端;)1.服务器代码1.1服务器类头文件(CS...
    99+
    2023-06-20
  • Django实现WebSocket在线聊天室功能(channels库)
    1.Django实现WebSocket在线聊天室 1.1 安装 pip install channels==2.3 (saas) F:\Desktop\Python_Study\...
    99+
    2022-11-12
  • ASP.net(C#)实现简易聊天室功能
    本文实例为大家分享了ASP.net(C#)实现简易聊天室功能的具体代码,供大家参考,具体内容如下 1.搭建框架 <html > <head>     <...
    99+
    2022-11-13
  • C++实现Window环境聊天室功能
    C++ Window环境聊天室,供大家参考,具体内容如下 最近闲来无事,想学习一下C++的并发编程和Socket信息传输,故以聊天室为载体进行学习。话不多说,代码开干。 聊天室分为多...
    99+
    2022-11-12
  • C++如何实现TCP聊天室功能
    小编给大家分享一下C++如何实现TCP聊天室功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!具体内容如下TCPServer.cpp:// TCPSer...
    99+
    2023-06-20
  • Java基于UDP协议的聊天室功能
    UDP简述 UDP(User Datagram Protocol)协议是Internet 协议集支持的一个无连接的传输协议,中文名为用户数据报协议。它为应用程序提供了一种无需建立连接...
    99+
    2022-11-13
  • C#基于Socket实现多人聊天功能
    本文实例为大家分享了C#基于Socket实现多人聊天功能的具体代码,供大家参考,具体内容如下 服务器 服务器负责接受所有客户端发来的消息,和将接受到的问题群发到其他用户。 代码: u...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作