基于webapi的websocket聊天室(二)
上一篇 - 基于webapi的websocket聊天室(一)
消息超传缓冲区的问题
在上一篇中我们定义了一个聊天室WebSocketChatRoom。但是每个游客只分配了400个字节的发言缓冲区,大概100字。
如果需要发送更多内容呢?难道直接增大缓冲区?
这是一个办法。但还有其他办法。
多次接受消息
可以多次调用ReceiveAsync来接受消息。每次接收消息放在不同数组中,最后合并。
//WebSocketChatRoom.cs
/// <summary>
/// 多次接受消息
/// </summary>
/// <param name="client"></param>
/// <returns></returns>
public async Task<(List<byte> bytes, WebSocketMessageType MessageType)> GetBytes(WebSocket client)
{
IList<ArraySegment<byte>> byteSegments = new List<ArraySegment<byte>>();
WebSocketReceiveResult result;
do
{
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[400]);
byteSegments.Add(buffer);
result = await client.ReceiveAsync(buffer, CancellationToken.None);
} while (result.EndOfMessage==false);
// 将所有字节连接起来
List<byte> allBytes = new List<byte>();
for (int i = 0; i < byteSegments.Count; i++)
{
var segment = byteSegments[i];
if (i== byteSegments.Count-1)
{
allBytes.AddRange(segment.Take(result.Count));
}
else
{
allBytes.AddRange(segment);
}
}
return (allBytes,result.MessageType);
}
然后调整消息循环
//WebSocketChatRoom.cs
while(!client.CloseStatus.HasValue)
{
//使用新的方法
var bytesResult = await GetBytes(client);
//广播游客发言
if (bytesResult.MessageType == WebSocketMessageType.Text)
{
CascadeMeaasge(visitor, $"{visitor.Name}: " + UTF8Encoding.UTF8.GetString(bytesResult.bytes.ToArray()));
}
}
- 缺点
由于每次接受消息都会创建新的对象来接受消息,会频繁GC。
增加默认缓存区
简单的解决这个问题,就是每个连接分配一个固定大小的默认缓存区,当这个缓存区不够的时候才临时创建新的缓存区。
改造起来也简单。
就是多增加一个参数。然后再while中第一次使用defaultBuffer,之后再创建新的buffer。
//WebSocketChatRoom.cs
/// <summary>
/// 多次接受消息
/// </summary>
/// <param name="client"></param>
/// <param name="defaultBuffer"></param>
/// <returns></returns>
public async Task<(ArraySegment<byte> bytes, WebSocketMessageType MessageType)> GetBytes(WebSocket client, byte[] defaultBuffer)
{
IList<ArraySegment<byte>> byteSegments = new List<ArraySegment<byte>>();
WebSocketReceiveResult result;
int bufferSize = 400;
do
{
if (byteSegments.Count==0)
{
byteSegments.Add(defaultBuffer);
}
else
{
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[bufferSize]);
byteSegments.Add(buffer);
}
result = await client.ReceiveAsync(byteSegments.Last(), CancellationToken.None);
} while (result.EndOfMessage==false);
// 将所有字节连接起来
if (byteSegments.Count==1)
{
//ArraySegment是结构体,值类型,不会导致GC
return (new ArraySegment<byte>(defaultBuffer,0,result.Count), result.MessageType);
}
else
{
List<byte> allBytes = new List<byte>();
for (int i = 0; i < byteSegments.Count; i++)
{
var segment = byteSegments[i];
if (i == byteSegments.Count - 1)
{
allBytes.AddRange(segment.Take(result.Count));
}
else
{
allBytes.AddRange(segment);
}
}
var resultSegment = new ArraySegment<byte>(allBytes.ToArray());
return (resultSegment, result.MessageType);
}
}
然后调用这个方法的时候把默认缓冲区传进去即可
//WebSocketChatRoom.cs
//消息缓冲区。每个连接分配400字节,100个汉字的内存
var defaultBuffer = new byte[400];
//读数据
//消息循环
while (!client.CloseStatus.HasValue)
{
var bytesResult = await GetBytes(client, defaultBuffer);
//广播游客发言
if (bytesResult.MessageType == WebSocketMessageType.Text)
{
CascadeMeaasge(visitor, $"{visitor.Name}: " + UTF8Encoding.UTF8.GetString(bytesResult.bytes.Array,0,bytesResult.bytes.Count));
}
}
基于webapi的websocket聊天室(二)的更多相关文章
- 基于springboot的websocket聊天室
WebSocket入门 1.概述 1.1 Http #http简介 HTTP是一个应用层协议,无状态的,端口号为80.主要的版本有1.0/1.1/2.0. #http1.0/1.1/2.0 1.HTT ...
- 基于flask的网页聊天室(二)
基于flask的网页聊天室(二) 前言 接上一次的内容继续完善,今天完成的内容不是很多,只是简单的用户注册登录,内容具体如下 具体内容 这次要加入与数据哭交互的操作,所以首先要建立相关表结构,这里使用 ...
- Netty入门(一)之webSocket聊天室
一:简介 Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.高可靠性协议的服务器和客户端. 换句话说,Netty 是 ...
- 使用.NET Core和Vue搭建WebSocket聊天室
博客地址是:https://qinyuanpei.github.io. WebSocket是HTML5标准中的一部分,从Socket这个字眼我们就可以知道,这是一种网络通信协议.WebSocket是 ...
- 基于flask的网页聊天室(四)
基于flask的网页聊天室(四) 前言 接前天的内容,今天完成了消息的处理 具体内容 上次使用了flask_login做用户登录,但是直接访问login_requare装饰的函数会报401错误,这里可 ...
- websocket聊天室
目录 websocket方法总结 群聊功能 基于websocket聊天室(版本一) websocket方法总结 # 后端 3个 class ChatConsumer(WebsocketConsumer ...
- WebSocket聊天室demo
根据Socket异步聊天室修改成WebSocket聊天室 WebSocket特别的地方是 握手和消息内容的编码.解码(添加了ServerHelper协助处理) ServerHelper: using ...
- 基于flask的网页聊天室(三)
基于flask的网页聊天室(三) 前言 继续上一次的内容,今天完成了csrf防御的添加,用户头像的存储以及用户的登录状态 具体内容 首先是添加csrf的防御,为整个app添加防御: from flas ...
- 基于flask的网页聊天室(一)
基于flask的网页聊天室(一) 基本目标 基于flask实现的web聊天室,具有基本的登录注册,多人发送消息,接受消息 扩展目标 除基本目标外添加当前在线人数,消息回复,markdown支持,历史消 ...
- 用Java构建一个简单的WebSocket聊天室
前言 首先对于一个简单的聊天室,大家应该都有一定的概念了,这里我们省略用户模块的讲解,而是单纯的先说说聊天室的几个功能:自我对话.好友交流.群聊.离线消息等. 今天我们要做的demo就能帮我们做到这一 ...
随机推荐
- JDK11的新特性:新的HTTP API
目录 简介 使用HTTP Client请求的基本流程 创建HTTP Client 创建HTTP Request 发送HTTP请求 异步HTTP请求 总结 JDK11的新特性:新的HTTP API 简介 ...
- 将Map中对应的key和value赋值到对象中
BeanUtils位于import org.apache.commons.beanutils.BeanUtils包下 其使用方法: Map<String, Object> objectMa ...
- 【FAQ】视频编辑服务常见问题及解答
Q1问题描述 1. 访问贴纸等素材的时候提示"网络异常,请重试"怎么办? 2. 使用AI能力时,提示"errorCode:20124 errorMsg:Method no ...
- HMS Core手语服务荣获2022中国互联网大会“特别推荐案例”:助力建设数字社会
11月15日,HMS Core手语服务在2022(第二十一届)中国互联网大会 "互联网助力经济社会数字化转型"案例评选活动中,荣获"特别推荐案例". 经过一年多 ...
- 报名启动丨HMS Core. Sparkle应用创新论坛
图形领域将迎来哪些技术新进展?时下热门的3D.AR/VR和数字人等创新技术又会给应用开发带来哪些新的启发?以上问题,将在7月15日HMS Core. Sparkle应用创新论坛揭晓,赶快点击链接报名参 ...
- 在Mac系统上使用Qt调用摄像头不出图解决方法
需求:在Mac系统上,调用摄像头,实现旋转.缩放.处理视频帧等功能 问题:使用获取视频帧的方法,在Mac上调不起来摄像头 解决方法: 将视频窗口(QVideoWidget)和视频帧(QVideoFra ...
- (数据科学学习手札159)使用ruff对Python代码进行自动美化
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,在日常编写Python代码的过 ...
- 算法小白刷了一周 LeetCode 后的思考
Hi,我是 itchao 我自己工作有 2 两年多的前端开发经验,但是数据结构与算法一直不好,基本就是一个算法小白的水平. 听说大公司面试都要手写算法题,最近为了以后能去更好的公司,然后其实心里比较着 ...
- HDC2021技术分论坛:HarmonyOS低代码开发介绍
作者:sunyuhui,wangxiaoyan,华为2012实验室软件IDE专家 什么是低代码开发?低代码开发主要特点有哪些?如何利用低代码开发原子化服务?本文带你一探究竟~ 一.什么是Harmony ...
- 面向开发者的HarmonyOS 3.0 Beta发布
原文:https://mp.weixin.qq.com/s/y0h5CUMbuFchwT7g-AqaBQ,点击链接查看更多技术内容. 2021年10月,我们面向开发者发布了HarmonyOS 3.0 ...