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(上)中了解了这个缓存类大概的功能是什么?那么接下来就要看看这些功能是如何实现的? 再次强调,不管是图片的缓存还是其他各种不同形式的缓存,在原理上都极 ...
随机推荐
- STM32学习笔记:创建标准库工程模板
背景 标准库下载:地址 本章的项目可以在这里下载. STM32作为一类经典的MCU.本人从2018年1月1日开始对于STM32系列单片机的学习. 本人所持的型号为:STM32F429ZI-DISCOV ...
- 流程图渲染方式:Canvas vs SVG
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:霁明 背景 我们产品中会有一些流程图应用,例如审批中心的审 ...
- WPF在.NET9中的重大更新:Windows 11 主题
在2023年的2月20日,在WPF的讨论区,WPF团队对路线的优先级发起了一次讨论. 对三个事项发起了投票. 第一个是Windows 11 主题 第二个是更新的控件 第三个是可空性注释 最终Windo ...
- mac idea 更换主题
使用 主题一 xcode-dark-theme:点我直达 主题二 one-dark-theme:点我直达 主题三 dark-purple-theme:点我直达 主题四(推荐) vuesion-them ...
- 【JavaScript高级04】作用域和作用域链
1,作用域 作用域表示的是变量的有效区域,JavaScript中作用域分为全局作用域和函数作用域(在es6之前没有块作用域).其确定时间为编写成功之后就已经确定好了. 作用域的作用是用来隔离变量,不同 ...
- LeetCode102.二叉树的层序遍历
LeetCode题目链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/submissions/548489149/ 题 ...
- 入门Vue+.NET 8 Web Api记录(一)
做自己感觉有意思的或者能解决自己需求的项目作为入门,我觉得是有帮助的,不会觉得那么无聊. 一个最简单的前后端分离项目应该是怎么样的? 我觉得就是前端有个按钮,点击向后端发送一个get请求,获取到数据后 ...
- Redis内存回收与缓存问题
内存回收: 1.过期key处理 通过expire命令给key设置ttl Redis本身是KV型数据库,所有数据都存在RedisDB结构体中,其中有两张哈希表 dict:用于存放KV(这里K是K,V是V ...
- 倒装句&强调句
倒装句 你[吃][胡萝卜]了吗? 吃胡萝卜了吗,[你]? 强调点不同 汉语常见于口语表达 英语则常见于书面用语 英语的语序是 主语 谓语(动词) 通常把谓语动词提前 1.完全倒装句 谓语部分完全放在主 ...
- 一次url请求全过程
一次url请求全过程 1,从宏观总体来看url请求全流程 2,从家庭实际网络架构来看一看网络是如何搭建和传输的 3,从网络七层协议的角度来看一看网络在各个层次之间的传输过程 4,从三次握手四次挥手的角 ...