回顾

之前已经写过关于《WebSocket 原生socket实现》和《.Net Core WebSocket 服务端与客户端完整示例》以及《基于.Net TcpListener 实现 WebSocketServer 通讯》。

其中除了 《.Net Core WebSocket 服务端与客户端完整示例》外,都是基于自己对Websocket协议的实现,这种实现在生产环境的时候,会有各种需要解决的问题,那么,就又回到了WebSocket的协议上去了。

所以,还是缺少一种轻量级的WebSocket客户端和服务端的支持,对于那些不想用第三方框架的人来说(第三方可能重,也可能复杂),所以,一个官方支持websocket使用,才是最好的。

这样,就不用自己去实现握手啊,Websocket底层协议了,以及Websocket实现的大包分包了和所谓socket的粘包,半包了。

正视WebSocket协议

之前可能都是简单的使用,并没有太过认真的去瞧这个协议。

现在认真去看,才发现,其实WebSocket已经把所谓的大包分包和socket的粘包,掉包(半包)等问题通过它自己的协议给解决了。

Websocket 自己还实现了ping和pong心跳支持。

这对通过原生socket支持来讲,相当于已经有人把使用socket的顾虑都给解决了,还是通过标准协议解决的,那么,我们使用的时候,应该更加简单,方便才对,而不是更加的复杂,难用。

这是我对这个协议又深入研究后的结果。

用新的方法实现WebSocket服务端

这里我介绍除了 《.Net Core WebSocket 服务端与客户端完整示例》的另外三种实现方式,主要是针对服务端,客户端的话,直接用ClientWebSocket就搞定了。

原生socket支持WebSocket Server

大部分在刚开始实现的时候,因为找不到库,只能用第三方,或者自己使用协议实现。

但是,其实,也是可以直接把Socket 转为 WebSocket对象的,这个方法,我也是在看官方源码的时候,找到的,才知道它的用处(网上一搜,用的人真少。)

后来发现少的原因,原来这个方法的支持是在.NET Core 2.1版本之后才有的。

原生的实现都得自己实现握手协议,也很简单。

WebSocketHelper.cs

/// <summary>/// WebSocket帮助类/// </summary>public static class WebSocketHelper{/// <summary>/// 协议处理-http协议握手/// </summary>public static byte[] HandshakeMessage(string data){/// <summary>/// 获取返回验证的key/// </summary>/// <param name="key"></param>/// <returns></returns>static string getResponseKey(string key){var MagicKey = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";if (string.IsNullOrEmpty(key)){return string.Empty;}else{key += MagicKey;key = Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key.Trim())));return key;}}string key = string.Empty;string info = data;//一步一步来string[] list = info.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);foreach (var item in list.Reverse()){if (item.IndexOf("Sec-WebSocket-Key") > -1){key = item.Split(new string[] { ": " }, StringSplitOptions.None)[1];break;}}//获取标准的keykey = getResponseKey(key);//拼装返回的协议内容var responseBuilder = new StringBuilder();responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + "\r\n");responseBuilder.Append("Upgrade: websocket" + "\r\n");responseBuilder.Append("Connection: Upgrade" + "\r\n");responseBuilder.Append("Sec-WebSocket-Accept: " + key + "\r\n\r\n");return Encoding.UTF8.GetBytes(responseBuilder.ToString());}}

核心代码

主要是对 socket 转 websocket server对象部分。

socket = ServerSocket.Accept();
WebSocket = WebSocket.CreateFromStream(new NetworkStream(socket), true, null, TimeSpan.FromSeconds(5));

原生socket接收到的客户端socket对象,直接转换就可以了。

TcpListener 支持WebSocket Server

大致同上,同一个原理,都需要自己处理握手

TcpClient s = listener.AcceptTcpClient();
WebSocket = WebSocket.CreateFromStream(s.GetStream(), true, null, TimeSpan.FromSeconds(5));

HttpListener 方式实现 WebSocket Server

这种方式,是我认为最轻量化的实现方式,连握手都不需要处理。

HttpListenerContext httpListenerContext = await this.listener.GetContextAsync();
HttpListenerWebSocketContext webSocketContext = await httpListenerContext.AcceptWebSocketAsync(null);
WebSocket = webSocketContext.WebSocket;

方式对比

加上以前的方案,目前一共有四种官方实现WebSocket Server 的方案。

  1. 1. asp.net core useWebSocket

  2. 2. socket WebSocket.CreateFromStream

  3. 3. tcpListener WebSocket.CreateFromStream

  4. 4. HttpListener AcceptWebSocketAsync

我个人认为,最好的方式就是第一种和第四种。其他两种自己还要实现握手。

另外,第一种与第四种的区别是起服务的引擎不同。asp.net core 是内置了 Kestrel 与 HTTP.sys 两种 webserver 服务引擎,而 HttpListener 可能就是默认的实现了 (具体也没查到),相对来讲更轻量一些。

结果展示

测试的大致逻辑是

  1. 1. 先启动服务端,再启动客户端

  2. 2. 客户端循环发送数据,先发送19次文字,再发送一个633M的视频大文件

  3. 3. 服务端收到后,如果是文字,就回复给客户端,如果不是文字,就输出大文件的大小

这个逻辑用来测试,应该没啥大问题。

socket 方案 1

tcpListener 方案 2

HttpListener 方案 3

需注意

特别是发送的操作,发送本身不能并发。

官方 资料引用 [2]

所以,在处理接收的时候,我们一般都是一个接收,但是,发送的地方经常被忽视。这个地方需要特殊处理的。

总结

只有复杂的实际应用才能深入了解各个方面,果真是天降大任于斯人也,深入挖掘才能掌握更多知识。

还是要勤于思考,勤于总结,我发现好多自己写过的东西都直接帮助到了我,这也许就是反哺己身吧。

资料引用

https://learn.microsoft.com/zh-cn/dotnet/api/system.net.websockets.websocket.createfromstream

https://learn.microsoft.com/en-us/dotnet/api/system.net.websockets.clientwebsocket.sendasync

代码地址

https://github.com/kesshei/WebSocketServerDemo2.git

https://gitee.com/kesshei/WebSocketServerDemo2.git

技术群:添加小编微信并备注进群

小编微信:mm1552923

公众号:dotNet编程大全

.Net Core 实现WebSocket Server 的另外三种方式相关推荐

  1. WebSocket不同版本的三种握手方式以及一个Netty实现JAVA类

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 一.We ...

  2. SQL Server数据库的三种恢复模式:简单恢复模式、完整恢复模式和大容量日志恢复模式...

    SQL Server数据库的三种恢复模式:简单恢复模式.完整恢复模式和大容量日志恢复模式 这篇文章主要介绍了SQL Server数据库的三种恢复模式:简单恢复模式.完整恢复模式和大容量日志恢复模式,需 ...

  3. SQL Server数据库的三种恢复模式

    SQL Server数据库的三种恢复模式:简单恢复模式.完整恢复模式和大容量日志恢复模式. sql server数据库提供了三种恢复模式:完整,简单和大容量日志,这些模式决定了sql server如何 ...

  4. SQL Server数据库的三种恢复模式:简单恢复模式、完整恢复模式和大容量日志恢复模式

    这篇文章主要介绍了SQL Server数据库的三种恢复模式:简单恢复模式.完整恢复模式和大容量日志恢复模式,需要的朋友可以参考下 如何图形界面下修改恢复模式 找到你想修改的数据库 右键 > 属性 ...

  5. Spring 异常处理三种方式

    Spring 异常处理三种方式 异常处理方式一. @ExceptionHandler 异常处理方式二. 实现HandlerExceptionResolver接口 异常处理方式三. @Controlle ...

  6. 够狠 | 单点登录三种方式,够狠!够劲爆!

    Hi! 我是小小,今天是本周的最后一篇,本篇将会着重讲解单点登录的三种方式. 前言 单点登录分为三种机制,这三种机制分别为http无状态协议,会话机制,登录机制等这三种机制. http无状态协议 we ...

  7. Redis存储对象的三种方式

    存储对象的三种方式分别为: 1.将对象序列化后保存到Redis 2.将对象用FastJSON转为JSON字符串后存储 3.将对象用Hash数据类型存储 序列化工具类SerializeUtil publ ...

  8. springboot读取配置文件的三种方式

    项目中springboot读取配置文件的三种方式: 1.使用Environment 2.使用@Value 3.使用@ConfigurationProperties注解映射到bean中,定义一个User ...

  9. ios 应用和电脑共享文件夹_堪比AirDrop,苹果 iPhone与Windows电脑互传文件的三种方式...

    如果你是苹果全家桶用户,一定会对 「AirDrop(隔空投送)」 功能赞誉有加,使用 AirDrop 可以在 iPhone 与 MacBook.iPad 等设备之间快速传递照片.视频或文件. 遗憾的是 ...

最新文章

  1. 广度优先搜索(BFS)模板
  2. 通知 | 2020年度“RONG”奖学金入围答辩名单公布
  3. [零基础学JAVA]Java SE应用部分-32.Java网络编程
  4. python函数映射教学,Python 序列与映射的解包操作
  5. Linux有问必答:怎么用CheckInstall从源码创建一个RPM或DEB包
  6. 杭电acm2151题java的解法,杭电ACM题型分类
  7. 3 个月如何从小白到 Python 高手?清华博士带你入门带你飞!
  8. 讲真话的朋友才是我们需要的!
  9. c语言实验题——字符串排序,C语言中实现“三个数由小到大排序”的多种方法浅析...
  10. RabbitMQ liunx-centos 安装过程记录
  11. unity平行光太亮?物体发白?可能你使用了2个或多个平行光
  12. FPGA学习笔记---3种乘法器的比较
  13. 单例模式Java的七种写法
  14. 复杂系统学习(五):细胞自动机 I:1D 和 2D CAs
  15. python课程设计的心得体会_数据库课程设计心得体会精选篇
  16. 什么是人工智能?(科普)
  17. 阿里巴巴(杭州)转正答辩失败流水账
  18. java dismiss_为什么我的dismiss()方法无法关闭自定义警报对话框
  19. python求三重积分_python Scipy积分运算大全(一重、二重及三重积分)
  20. PostgreSQL:六. PostgreSQL函数

热门文章

  1. ROS专题----tf和tf2坐标变换
  2. 高项、高级项目管理师论文-风险管理
  3. sanicOpenApi 学习
  4. 鲁班H5页面生成工具
  5. Calendars - 日历插件
  6. java 线程管理_Java提供的线程池来创建多线程,进一步优化线程管理。
  7. 【Android之OkHttp介绍】
  8. 中国科大: 那些杀手都很冷[ZT]
  9. 【渝粤题库】陕西师范大学202501 法语(二)作业
  10. 机器人瓦力 配乐_机器人瓦力中的插曲是什么?