• 写在开始
  • 技术点
    • 接受方式
    • 判读在线方式
    • 接受数据
    • 发送数据
  • 敬上代码
    • 入口函数
    • 消息处理
    • 单聊实现
  • 传送门:
回到顶部

写在开始

上面一篇写了一篇使用WebSocket做客户端,然后服务端是socke代码实现的。传送门:webSocket和Socket实现聊天群发

本来我是打算写到一章上的,毕竟实现的都是一样的功能,后来想了想就没写在一起,主要是两个方面,

一个原因是这是另一种实现服务方式,放在一起看着有点乱。单独写也方便查阅。二是写是分开写的回家晚上写一点,不能直接在原文上写,就重新起来一个草稿,但是写完就感觉有点懒,不想整合到一块了。嘿嘿,,,

所以对开头说的不明白的同学可以先看一下前面的东西。看一下基础,事半功倍哦。

这一篇不做功能的更改,既然我们使用了WebSocket为什么不使用到底哪,我不喜欢socket的里面出现的打包请求连接数据处理和发送数据处理。可以没有问题啊。那你继续往下看吧。

首先WebSocket服务器这篇我们还是实现的6个功能:

  • 单聊:可以指定人进行聊天。
  • 群发:这个的意思就是当前服务器内的所有人包含自己,这个就跟一个推送效果一样。
  • 开启连接(客户端):通知除自己以外的所有用户
  • 关闭连接(客户端):通知除自己以外的所有用户
  • 群组A:实现一个群组名字为A
  • 群组B:实现一个群组名字为B
回到顶部

技术点

前端写法都是一样的我就不做过多的叙述了,这里只要是针对socket协议的方法进行修改成WebSocket形式。

首先我这次是把服务写成了一般处理程序进行挂载的。(有些有强迫症的小伙伴想改访问路由路径可以参考一下:mvc中路由的映射和实现IHttpHandler挂载

我在本示例就是把放在model下的一个一般处理程序,改写成了socket路径.

原来访问是:http“//http://localhost:端口号/文件夹位置/SocketServer.ashx

改完之后是:http“//http://localhost:端口号/socket/SocketServer.ashx

在实际项目中可以不暴露文件的真是路径位置,还是有点用处的。

不得不说WebSocket确实不错,比如接受发送数据解析方法都给封装好了。

接受方式

既然使用WebSocket做协议当然接受就不用用socket而是使用WebSocket啦。通过在接受到请求后获取上下文中的WebSocket。

            //创建新WebSocket实例
            WebSocket myClientSocket = context.WebSocket;            string userId = context.QueryString["userId"];

在这里我们有一点变化就是socke用户是通过socket随机获取的,这里我修改成了页面传输。前台代码:

 var userId = parseInt(Math.random() * (999999 - 100000 + 1) + 100000, 10);
        console.log(userId)
        ws = new WebSocket('ws://' + window.location.hostname + ':' + window.location.port + '/socket?userId=' + userId);

判读在线方式

WebSocket有单独的状态来进行在线的判断,不用我们自己写判断处理还是比较好的。

                            #region 关闭Socket处理,删除连接池
                            if (myClientSocket.State != WebSocketState.Open)//连接关闭
                            {
                                if (ListUser.ContainsKey(userId)) ListUser.Remove(userId);//删除连接池
                                break;
                            }
                            #endregion

接受数据

WebSocket也没有辜负我们的期望,接受数据的处理也不需要我们处理的,使用ReceiveAsync方法可以得到消息字节,我们只需要定义一个字节数组段用来接受即可,例如:

                        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);//定义字节数组
                        WebSocketReceiveResult result = await myClientSocket.ReceiveAsync(buffer, CancellationToken.None);//获得字节                        string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息

是不是感觉特别的方便,没有了那些乱七八糟的处理了。看着还是挺舒心的。

发送数据

既然接受数据都有单独的方法封装,发送消息没有道理没有的,是的发送使用SendAsync方法,使用形式和ReceiveAsync类似,首先定义一个字节数组段用来存放内容,例如:

                        ArraySegment<byte> buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes($"用户({userIdA}=>{userIdB}):{msg}"));
                        socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);

这样子就是一个发送过程,先把要发送的字符串转换成字节数组段,然后把这个数组段使用SendAsync发送出去就可以了。

注:在上面的两个方法中我们都看到了ArraySegment这个东西,他到底是个什么哪,他是一个命名在System命名空间下的一个结构体。类似与Array数组但是他又不是数组,为什么这么说,因为他可以接受数组段,他可以只保存内容中的一部分而不是全部。就像别人说的小抽屉一样。我是把他理解成先把他放到这里当作数据缓存区,等真实发送的时候进行发送数据。WebSocketMessageType是一个枚举类型,通过F12可以看到:

    // 摘要:
    //     指示消息类型:
    public enum WebSocketMessageType
    {
        //
        // 摘要:
        //     该消息是明文形式。
        Text = 0,
        //
        // 摘要:
        //     消息采用二进制格式。
        Binary = 1,
        //
        // 摘要:
        //     因为收到关闭的消息,接受已完成。
        Close = 2
    }
回到顶部

敬上代码

入口函数

一般处理程序中判断只接受WebSocket协议连接进入的运行:

            if (context.IsWebSocketRequest)
            {
                context.AcceptWebSocketRequest(Accept);
            }
            else
            {

            }

消息处理

下面就是同意连接后的主要方法,类似上一篇写的ReceiveMessage方法(接受消息),这里的处理存在一些改动,所以我就把所有代码贴上来了。

 1 #region 处理客户端连接请求
 2         /// <summary>
 3         /// 处理客户端连接请求
 4         /// </summary>
 5         /// <param name="result"></param>
 6         private async Task Accept(AspNetWebSocketContext context)
 7         {
 8             //创建新WebSocket实例
 9             WebSocket myClientSocket = context.WebSocket;
10             string userId = context.QueryString["userId"];
11
12             try
13             {
14
15                 string descUser = string.Empty;//目的用户
16                 while (true)
17                 {
18                     if (myClientSocket.State == WebSocketState.Open)
19                     {
20                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
21                         WebSocketReceiveResult result = await myClientSocket.ReceiveAsync(buffer, CancellationToken.None);
22
23                         #region 消息处理(字符截取、消息转发)
24                         try
25                         {
26                             #region 关闭Socket处理,删除连接池
27                             if (myClientSocket.State != WebSocketState.Open)//连接关闭
28                             {
29
30                                 if (ListUser.ContainsKey(userId))
31                                 {
32                                     //退出
33                                     SignOut(userId);
34                                     ListUser.Remove(userId);//删除连接池
35                                     Debug.WriteLine("当前退出用户:" + userId);
36                                 }
37                                 break;
38                             }
39                             #endregion
40                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
41                             string[] resultList = userMsg.Split(',');
42                             if (resultList[0] == "login")
43                             {
44                                 //登录
45                                 Login(userId);
46                                 #region 用户添加连接池
47                                 //第一次open时,添加到连接池中
48                                 if (!ListUser.ContainsKey(userId))
49                                     ListUser.Add(userId, myClientSocket);//不存在,添加
50                                 else
51                                     if (myClientSocket != ListUser[userId])//当前对象不一致,更新
52                                     ListUser[userId] = myClientSocket;
53                                 #endregion
54                                 Debug.WriteLine("当前登录用户:" + userId);
55                             }
56                             else if (resultList[0] == "all")
57                             {
58                                 //群发所有用户
59                                 GroupChat(userId, resultList[1]);
60                             }
61                             else if (resultList[0] == "groupA")
62                             {
63                                 //群组发送
64                                 GroupChatA("groupA", userId, resultList[1]);
65                             }
66                             else if (resultList[0] == "groupB")
67                             {
68                                 //群组发送
69                                 GroupChatA("groupB", userId, resultList[1]);
70                             }
71                             else
72                             {
73                                 //单聊
74                                 SingleChat(userId, resultList[0], resultList[1]);
75                             }
76
77                         }
78                         catch (Exception exs)
79                         {
80                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
81                         }
82                         #endregion
83                     }
84                     else
85                     {
86                         break;
87                     }
88                 }//while end
89             }
90             catch (Exception ex)
91             {
92                 Console.WriteLine("Error : " + ex.ToString());
93             }
94         }
95         #endregion

单聊实现

这里我就不把写的所有单聊,群里,实现群组方法贴上来了,实现的思路还是和以前一样,只是写法不同,我就写一个单聊作为代表示例贴上来。想看全部在下面下载源码就好了。

 #region 单聊
        public void SingleChat(string userIdA, string userIdB, string msg)
        {
            WebSocket socket = ListUser[userIdB];
            if (socket != null)
            {
                if (socket !www.leyou2.net = null && socket.State == WebSocketState.Open)
                {
                    ArraySegment<www.078881.cn byte> www.feifanyule.cn buffer =www.yongshiyule178.com new ArraySegment<byte>(Encoding.UTF8.GetBytes($"用户({userIdA}=>{userIdB}):{msg}"));
                    socket.SendAsync(buffer, WebSocketMessageType.Binary, true, CancellationToken.None);
                }
            }

        }
        #endregion
回到顶部

传送门:

基础版本实现简单的websocket:实现服务端webSocket连接通讯

完善websocket实现聊天示例:WebSocket和Socket实现聊天群发

springboot中的几种scope的更多相关文章

  1. 补习系列(3)-springboot中的几种scope

    目标 了解HTTP 请求/响应头及常见的属性: 了解如何使用SpringBoot处理头信息 : 了解如何使用SpringBoot处理Cookie : 学会如何对 Session 进行读写: 了解如何在 ...

  2. SpringBoot中的五种对静态资源的映射规则

    目录 1.​ webjars:以jar包的方式引入静态资源 2./** 访问当前项目的任何资源 3.首页index.html,被" /** "映射 4.自定义图标 / favico ...

  3. 聊聊 SpringBoot 中的两种占位符:@*@ 和 ${*}

    前言 在 SpringBoot 项目中,我们经常会使用两种占位符(有时候还会混用),它们分别是: @*@ ${*} 如果我们上网搜索「SpringBoot 的占位符 @」,大部分答案会告诉你,Spri ...

  4. redis(Springboot中封装整合redis,java程序如何操作redis的5种基本数据类型)

    平常测试redis操作命令,可能用的是cmd窗口 操作redis,记录一下 java程序操作reids, 操作redis的方法 可以用Jedis ,在springboot 提供了两种 方法操作 Red ...

  5. Springboot中关于跨域问题的一种解决方法

    前后端分离开发中,跨域问题是很常见的一种问题.本文主要是解决 springboot 项目跨域访问的一种方法,其他 javaweb 项目也可参考. 1.首先要了解什么是跨域 由于前后端分离开发中前端页面 ...

  6. springboot 中事件监听模型的一种实现

    目录 定义事件本身 定义事件源 定义监听者 一.需要实现 ApplicationListener 二.使用 @EventListener 注解 测试 项目结构 前言: 事件监听模型是一种常用的设计模式 ...

  7. springboot成神之——mybatis在spring-boot中使用的几种方式

    本文介绍mybatis在spring-boot中使用的几种方式 项目结构 依赖 WebConfig DemoApplication 方式一--@Select User DemoApplication ...

  8. SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法

    软件152 尹以操 首先谢谢大佬的简书文章:http://www.jianshu.com/p/45ad65690e33# 这篇文章中讲的是spring中使用spring data jpa,使用了xml ...

  9. 在springboot中使用Mybatis Generator的两种方式

    介绍 Mybatis Generator(MBG)是Mybatis的一个代码生成工具.MBG解决了对数据库操作有最大影响的一些CRUD操作,很大程度上提升开发效率.如果需要联合查询仍然需要手写sql. ...

随机推荐

  1. Charles拦截请求

    一.通过Charles抓包,可拦截请求并篡改交互信息 1.可篡改客户端向服务器发起的请求信息(服务器收到的是假消息) 2.可篡改服务器返回给客户端的响应结果(客户端看到的是假消息) 二.篡改用户请求 ...

  2. Linux学习记录(三)

    1.Linux的软件安装 1.1.jdk安装 注意:rpm与软件相关命令 相当于window下的软件助手 管理软件 步骤: 1)查看当前Linux系统是否已经安装java 输入 rpm -qa | g ...

  3. windows下安装python的包管理工具pip,scikit-learn

    打开https://pip.pypa.io/en/latest/installing.html#python-os-support 下载pip-get.py 进入python,执行pip-get.py ...

  4. swiper动画效果

    参考swiper官方网站:http://www.swiper.com.cn/ Swiper常用于移动端网站的内容触摸滑动: 结构展示:   纯javascript打造的滑动特效插件,面向手机.平板电脑 ...

  5. Oracle10g安装过程中的Configuration Assistant配置失败的问题。

    前几天安装Oracle的时候碰到了一个小问题,是在最后配置的时候,出现失败提示如下 失败提示:一些 Configuration Assistant 失败.强烈建议您此时重试这些 Configurati ...

  6. 洛谷P3371单源最短路径SPFA算法

    SPFA同样是一种基于贪心的算法,看过之前一篇blog的读者应该可以发现,SPFA和堆优化版的Dijkstra如此的相似,没错,但SPFA有一优点是Dijkstra没有的,就是它可以处理负边的情况. ...

  7. 10.VUE学习之使用lodash库减少watch对后台请求的压力

    问题描述 使用watch监听库里word的值的变化,获取新值后,用oxios发送的ajax异步请求, 此时会多次发送请求,浪费服务器资料. 解决办法 使用lodash库里的_.debounce函数延缓 ...

  8. vue之神奇的动态按钮

    今天我们将利用vue的条件指令来完成一个简易的动态变色功能按钮 首先我们还是要对vue进行配置,在上篇随笔中有相关下载教学. 然后我们要在html页面上搭建三个简易的按钮,颜色分别为紫,绿和蓝(颜色随 ...

  9. 科学计算库Numpy——排序

    矩阵按维度排序 使用np.sort()进行排序. 排序索引值 使用np.argsort()排序,返回排序后的索引值. 备注:array1[1,2]=1.2,array1[1,0]=5.6,array1 ...

  10. 初学python来进行odoo12版本开发

    这是我的第一篇博客.请多多指教! 首先要下载odoo-12的源代码 官方下载路径:          https://github.com/odoo/odoo/archive/12.0.zip 随便新 ...