C# WebSocket Fleck 源码解读
最近在维护公司旧项目,偶然发现使用Fleck实现的WebSocket主动推送功能,(由于前端页面关闭时WebSocket Server中执行了多次OnClone事件回调并且打印了大量的关闭日志,),后来我特地看了源码,这里做一些分享
github: https://github.com/statianzo/Fleck
在源码中,作者在 Samples 项目中贴心的准备了Server端和 前端Html文件供调试

打开后,我们稍微改动一下Server.cs类,模拟实际场景向客户端主动推送消息。

运行ConsoleApp项目,随后在浏览器中打开client.html,我们就可以看到客户端接收到很多主动推送的消息

关闭客户端后,此时我们会发现控制台上打印了好多“Close!”,并且抛出了异常,异常是从System.Net.Sockets.NetworkStream 抛出,说我们访问了已释放的对象。

大概猜测的是程序并发太高了,Socket已经关闭释放的同时,我们任然在向流写入byte字节发送消息。
接下来我们读一下源码
首先是 WebSocketServer.cs,构造方法中创建了 System.Net.Sockets.Socket类,并传递给 Fleck.SocketWrapper,后续和Socket相关的操作都是由SocketWrapper实例进行执行。SupportDualStack为True时表示启用IPV6

随后我们看一下 WebSocketServer.Start() 方法,方法的入参是一个Action,IWebSocketConnection 中我们定义了OnOpen、OnClose、OnMessage等方法。
Start()方法中给SocketWrapper(或System.Net.Sockets.Socket类)类绑定了侦听地址和端口。
ListenForClients() 方法为开始接收连接(Accept),如果有连接,则调用OnClientConnect()方法,OnClientConnect()方法调用中如果出现异常,则执行重启Socket工作。

我们再来看看OnClientConnect()方法做了什么,ListenForClients() 方法是继续侦听客户端连接,随后创建了WebSocketConnection类对象,然后开始connection.StartReceiving() 也就是读取消息内容。

我们可以简单的看一下Fleck.SocketWrapper类的实现,特别是Accept()方法和Receive()方法,其实就是Task执行BeginAccept()、EndAccept()、BeginRead() 和 EndRead() 方法,如果调用时出现异常,则执行Action<Exception>()方法。

接下来我们看一下WebSocketConnection类,首先是构造方法,
- socket:连接Socket实例。
- initialize:是我们在WebSocketServer 中配置的OnOpen、OnClone、OnMessage等方法。
- handlerFactory:是通过工厂模式创建出对应的Handle对象,其中实现了 Draft76Handler、Hybi13Handler、FlashSocketPolicyRequestHandler 等几种类,将收到的byte[]序列化成对应的消息。
- parseRequest:是RequestParser.Parse方法的委托,将byte[]通过UTF8序列化成中文,再通过正则表达式提取关键信息生成WebSocketHttpRequest对象。
其次是Read(List<byte>, byte[]) 方法。就是调用SocketWrapper(或System.Net.Sockets.Socket类)的 Receive()方法读取byte[]并交给Handle对象进行处理,如果byte[]长度为0,则表示关闭断开

最后是SendBytes(byte[], Action)方法,就是调用SocketWrapper(或System.Net.Sockets.Socket类)的 Send()方法,如果发送不成功,则会调用CloseSocket()方法关闭Socket(这就是为什么连接只有一个但多次触发OnClose事件原因)
Fleck 的核心功能已经讲解完了,其他类还有 WebSocketConnectionInfo、QueuedStream、SubProtocolNegotiator等类基本也是比较简单,这里就不展开讲解了。
C# WebSocket Fleck 源码解读的更多相关文章
- Flask(4)- flask请求上下文源码解读、http聊天室单聊/群聊(基于gevent-websocket)
一.flask请求上下文源码解读 通过上篇源码分析,我们知道了有请求发来的时候就执行了app(Flask的实例化对象)的__call__方法,而__call__方法返回了app的wsgi_app(en ...
- flask的请求上下文源码解读
一.flask请求上下文源码解读 通过上篇源码分析( ---Flask中的CBV和上下文管理--- ),我们知道了有请求发来的时候就执行了app(Flask的实例化对象)的__call__方法,而__ ...
- swoft| 源码解读系列二: 启动阶段, swoft 都干了些啥?
date: 2018-8-01 14:22:17title: swoft| 源码解读系列二: 启动阶段, swoft 都干了些啥?description: 阅读 sowft 框架源码, 了解 sowf ...
- SDWebImage源码解读之SDWebImageDownloaderOperation
第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
- SDWebImage源码解读 之 NSData+ImageContentType
第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...
- SDWebImage源码解读 之 UIImage+GIF
第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...
- SDWebImage源码解读 之 SDWebImageCompat
第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...
- SDWebImage源码解读_之SDWebImageDecoder
第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...
- SDWebImage源码解读之SDWebImageCache(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
- SDWebImage源码解读之SDWebImageCache(下)
第六篇 前言 我们在SDWebImageCache(上)中了解了这个缓存类大概的功能是什么?那么接下来就要看看这些功能是如何实现的? 再次强调,不管是图片的缓存还是其他各种不同形式的缓存,在原理上都极 ...
随机推荐
- Linux 驱动:LED子系统
Linux 驱动:LED子系统 背景 在调试aw9523的时候,为了实现客户要的一个效果.需要修改驱动,但是大概看了一下驱动,但是因为不太熟悉LED子系统,所以有点云里雾里. 参考: https:// ...
- 【深度学习 有效炼丹】多GPU使用教程, DP与DDP对比, ray多线程并行处理等 [GPU利用率低的分析]
️ 前言 更新日志: 20220404:新增一个DDP 加载模型时显存分布不均问题,见目录遇到的问题及解决处 主要是上次server12 被自己一个train 直接线程全部拉满了(没错 ... ser ...
- QT自定义右键菜单
利用QMenu和QAction可以实现非常实用的右键菜单功能.具体实现思路如下: 1.在xxx.h文件中添加如下头文件 #include <QMenu> #include <QCon ...
- 深入理解 Vue 3 组件通信
在 Vue 3 中,组件通信是一个关键的概念,它允许我们在组件之间传递数据和事件.本文将介绍几种常见的 Vue 3 组件通信方法,包括 props.emits.provide 和 inject.事件总 ...
- 关于构建一个可视化+code系统的思路
思路是有参考UE的现有功能,加之前的逻辑. 大概分为三个模块: 底层, 即native层 ,这一层实际上分为三个部分: 1.GUI层的解析,2.数据存储 3.Code的解析 这三部分关键在于他们 ...
- PixiJS源码分析系列:第三章 使用 canvas 作为渲染器
使用 canvasRenderer 渲染 上一章分析了一下 Sprite 在默认 webgl 渲染器上的渲染,这章让我们把目光聚集到 canvasRenderer 上 使用 canvas 渲染器渲染图 ...
- httpclient,轻量级idea集成测试工具
优点:不用新开一个网页,具有测试数据保存功能,不需要配置即用(对比swagger) 不会特别占内存(对比postman) 使用方法:idea中安装插件 controller方法中点击 选择对应 ...
- .NET 开源快捷的数据库文档查询和生成工具
前言 在实际项目开发中,需求变更和项目迭代是常态.要求我们能够迅速响应,对数据库结构进行相应的调整,如添加新表.更新现有表结构或增加字段等. 为了确保团队成员之间的信息同步,实时更新和维护数据库文档变 ...
- Fiddler使用界面介绍-右侧面板
右侧面板是对左侧请求进行解析的面板,点击左侧的请求右侧面板就会出现分析数据 1.Statistics关于HTTP请求的性能 2.Inspectors请求内容,包含请求数据和响应数据 3. AutoRe ...
- Jmeter函数助手34-digest
digest函数用于返回特定哈希算法的加密值. 算法摘要:填入算法,如MD2.MD5.SHA-1.SHA-224.SHA-256.SHA-384.SHA-512 String to be hashed ...