基于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就能帮我们做到这一 ...
随机推荐
- 王莉:将开发文档英文化和本地化,我们努力让OpenHarmony走向全球
编者按:在 OpenHarmony 生态发展过程中,涌现了大批优秀的代码贡献者,本专题旨在表彰贡献.分享经验,文中内容来自嘉宾访谈,不代表 OpenHarmony 工作委员会观点. 王莉 华为技术有限 ...
- Avalonia中的自绘控件
在构建用户界面时,控件扮演着至关重要的角色.它们不仅负责展示内容,还处理用户的交互.然而,有时标准的控件库可能无法满足我们的需求,这时自绘控件就显得尤为重要.在Avalonia UI框架中,自绘控件允 ...
- openGauss 列存表PSort索引
openGauss 列存表 PSort 索引 概述 PSort(Partial sort) Index 是在列存表的列上建的聚簇索引.CUDesc 上有每个 CU 的 min 和 max 值,但如果业 ...
- 2、androidStudio调用Unity方法
1.导入Unity的Classes.jar文件 (1).首先找到这个包在哪 Unity版本为5.0之前时,classes.jar的路径: unity的安装路径\Editor\Data\Playback ...
- 基于locust全链路压测系统
2021年中旬就计划着搭建一套压测系统,大约9月份已经搭建完成,使用至今还是比较稳定了,分享一下搭建思路及过程: 为什么选择Locust呢,因为Locust可以仅需要执行命令就可以完成压测任务,并且集 ...
- 《c#高级编程》第2章C#2.0中的更改(四)——空值类型
一.概念 在C#中,空值类型(Nullable Types)是一种特殊的数据类型,它可以包含正常值或者一个null值.当我们需要在程序中处理可能不存在的值时,空值类型就会派上用场. 空值类型的语法形式 ...
- PostgreSQL 14.4的安装以及使用以及一些安装的异常
PostgreSQL 14的安装以及使用 因为公司的一些要求,可能要换数据库,虽然之前装过,但是版本感觉还是新一点比较好,所以重新装一下 首先下载文件,直接去官网下载就行 https://www.en ...
- 【走进RDS】之SQL Server性能诊断案例分析
简介: 数据库性能诊断不仅对其数据库技能要求较高,而且需要大量的前期准备工作,如收集各种性能基线.性能指标和慢SQL日志等,尤其是面对多数据库性能调优时,往往事倍功半. 客户的困扰 前几天某程序员小王 ...
- 使用AnalyticDB轻松实现以图搜图和人脸检索
1. 背景 以图搜图在生活中有着广泛的应用, 当我们在电视上看到有人穿着一件美丽的裙子或者帅气的球鞋也想拥有时, 我们可以拍张照片然后打开淘宝然后上传照片就可以快速的找到这个商品. 我们看到一张电影截 ...
- 技术揭秘:从双11看实时数仓Hologres高可用设计与实践
简介:本文将会从阿里巴巴双11场景出发,分析实时数仓面临的高可用挑战以及针对性设计. 2021年阿里巴巴双11完美落下为帷幕,对消费者来说是一场购物盛宴,对背后的业务支撑技术人来说,更是一场年度大考 ...