上一篇 - 基于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聊天室(二)的更多相关文章

  1. 基于springboot的websocket聊天室

    WebSocket入门 1.概述 1.1 Http #http简介 HTTP是一个应用层协议,无状态的,端口号为80.主要的版本有1.0/1.1/2.0. #http1.0/1.1/2.0 1.HTT ...

  2. 基于flask的网页聊天室(二)

    基于flask的网页聊天室(二) 前言 接上一次的内容继续完善,今天完成的内容不是很多,只是简单的用户注册登录,内容具体如下 具体内容 这次要加入与数据哭交互的操作,所以首先要建立相关表结构,这里使用 ...

  3. Netty入门(一)之webSocket聊天室

    一:简介 Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.高可靠性协议的服务器和客户端. 换句话说,Netty 是 ...

  4. 使用.NET Core和Vue搭建WebSocket聊天室

    博客地址是:https://qinyuanpei.github.io.  WebSocket是HTML5标准中的一部分,从Socket这个字眼我们就可以知道,这是一种网络通信协议.WebSocket是 ...

  5. 基于flask的网页聊天室(四)

    基于flask的网页聊天室(四) 前言 接前天的内容,今天完成了消息的处理 具体内容 上次使用了flask_login做用户登录,但是直接访问login_requare装饰的函数会报401错误,这里可 ...

  6. websocket聊天室

    目录 websocket方法总结 群聊功能 基于websocket聊天室(版本一) websocket方法总结 # 后端 3个 class ChatConsumer(WebsocketConsumer ...

  7. WebSocket聊天室demo

    根据Socket异步聊天室修改成WebSocket聊天室 WebSocket特别的地方是 握手和消息内容的编码.解码(添加了ServerHelper协助处理) ServerHelper: using ...

  8. 基于flask的网页聊天室(三)

    基于flask的网页聊天室(三) 前言 继续上一次的内容,今天完成了csrf防御的添加,用户头像的存储以及用户的登录状态 具体内容 首先是添加csrf的防御,为整个app添加防御: from flas ...

  9. 基于flask的网页聊天室(一)

    基于flask的网页聊天室(一) 基本目标 基于flask实现的web聊天室,具有基本的登录注册,多人发送消息,接受消息 扩展目标 除基本目标外添加当前在线人数,消息回复,markdown支持,历史消 ...

  10. 用Java构建一个简单的WebSocket聊天室

    前言 首先对于一个简单的聊天室,大家应该都有一定的概念了,这里我们省略用户模块的讲解,而是单纯的先说说聊天室的几个功能:自我对话.好友交流.群聊.离线消息等. 今天我们要做的demo就能帮我们做到这一 ...

随机推荐

  1. 本周四晚19:00知识赋能第七期第3课丨OpenHarmony WiFi扫描仪实现

    8月25日19:00~20:00,第七期知识赋能第三节直播就要开始啦!如果你是缺乏实战经验的学生,如果你是初出茅庐的职场新人,如果你是想参与开源的贡献者,那么本期的直播课将不容错过!通过本期直播,开发 ...

  2. 本周四晚19:00知识赋能第六期第5课丨OpenHarmony WiFi子系统

    OpenAtom OpenHarmony(以下简称"OpenHarmony")开源开发者成长计划项目自 2021 年 10 月 24 日上线以来,在开发者中引发高度关注. 成长计划 ...

  3. 数据库SQL(MSSQLSERVER)服务启动错误代码3414

    昨天永和客户联系我,说他们的前台系统报错了,给我发了报错的图片.看到错误的第一眼就知道是数据库出问题了,连不上sql Server. 虽然知道是数据库出问题了,但是刚开始的时候没有打开SQL Serv ...

  4. openGauss数据库源码解析——慢SQL检测

    openGauss 数据库源码解析--慢 SQL 检测 慢 SQL 检测的定义: 基于历史 SQL 语句信息进行模型训练,并用训练好的模型进行 SQL 语句的预测,利用预测结果判断该 SQL 语句是否 ...

  5. Docker之离线安装和在线安装

    一.离线安装 1.软件包下载 https://download.docker.com/linux/static/stable/x86_64/ 2.安装docker tar xvf /opt/docke ...

  6. 重新整理数据结构与算法(c#)—— 二叉树排序树补删除节点[二十二]

    前言 续前一章. 正文 删除节点规则: 1.假如删除的是叶子节点,让他的父节点,断开和它的联系. 2.如果删除节点右左子树或者右子树的话,那么应该这样. 如果删除节点是它的父节点的左节点,而删除节点有 ...

  7. szfpga 高云gowin国产开发板GW2AR-18核心板fpga cpld测试板

    1. 概述 国产FPGA是最近几年起来的产品,具有性价比高特点.而GOWIN属于国产FPGA成员,在服务和芯片都是比较大的优势,很多用户都用在LED控制,电机控制,PLC设备上,以及用于替换Latti ...

  8. 用积木讲运维,这样的IT人太会了

    简介: 日志服务SLS提供数据采集.加工.分析.告警可视化与投递功能,为AIOps.大数据分析.运营服务.大数据安全等场景提供支撑,并能以搭积木的方式适配各类运维场景,辅助企业的IT决策.近日,日志服 ...

  9. Nacos 2.0 升级前后性能对比压测

    简介: Nacos 2.0 通过升级通信协议和框架.数据模型的方式将性能提升了约 10 倍,解决继 Nacos 1.0 发布逐步暴露的性能问题.本文通过压测 Nacos 1.0,Nacos 1.0 升 ...

  10. dotnet 5 的 bin 文件夹下的 ref 文件夹是做什么用的

    本文来和大家聊聊在 dotnet 5 和 dotnet 6 或更高版本的 dotnet 构建完成,在 bin 文件夹下,输出的 ref 文件夹.在此文件夹里面,将会包含项目程序集同名的 dll 文件, ...