ASP.NET Web API上实现 Web Socket
1. 什么是Web Socket
Web Socket是Html5中引入的通信机制,它为浏览器与后台服务器之间提供了基于TCP的全双工的通信通道。用以替代以往的LongPooling等comet style的实时解决方案。基于它们之间的比较以及Web Socket的优势参考https://www.websocket.org/quantum.html.
2. Web Socket如何工作
Connect
Web Socket在建立之前需要先与后台服务器进行握手。具体来说通过如下Http请求:
- GET /chat HTTP/1.1
- Host: server.example.com
- Upgrade: websocket
- Connection: Upgrade
- Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
- Sec-WebSocket-Protocol: chat, superchat
- Sec-WebSocket-Version: 13
- Origin: http://example.com
后台服务器如果支持切换到WebSocket,会返回如下Response:
- HTTP/1.1 101 Switching Protocols
- Upgrade: websocket
- Connection: Upgrade
- Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
- Sec-WebSocket-Protocol: chat
浏览器收到该Response会切换到基于当前TCP连接的WebSocket通道。
Data Transfer
连接建立后,浏览器端可以和服务器发送Text类型的消息进行全双工的通信,类似于基于TCP的Socket通信。
Disconnect
当浏览器或者后台服务器想终止通信,需向对方发送类型为Close的消息,并等待对方收到消息并确认后连接断开。
3. 浏览器,服务器支持情况
参考维基百科,目前浏览器的支持情况如下:
IE | Chrome | Firefox | Safari | Opera | ||
10+ | 16+ | 11+ | 6+ | 12.10+ |
IIS从8.0开始支持Web Socket
好了,很长的铺垫之后正式进入Coding:
1. 为了接受浏览器端的握手请求,我们需要定义一个Web Api接口接受握手请求
- [RoutePrefix("api/chat")]
- public class ChatController : ApiController
- {
- private static List<WebSocket> _sockets = new List<WebSocket>();
- [Route]
- [HttpGet]
- public HttpResponseMessage Connect(string nickName)
- {
- HttpContext.Current.AcceptWebSocketRequest(ProcessRequest); //在服务器端接受Web Socket请求,传入的函数作为Web Socket的处理函数,待Web Socket建立后该函数会被调用,在该函数中可以对Web Socket进行消息收发
- return Request.CreateResponse(HttpStatusCode.SwitchingProtocols); //构造同意切换至Web Socket的Response.
- }
- }
2. 为了对Web Socket进行消息收发,需要定义Web Socket的消息收发函数(以前的.net 版本是接受一个实现特定接口的对象,新版改成了接受一个函数,总觉得怪怪的),代码如下:
- public async Task ProcessRequest(AspNetWebSocketContext context)
- {
- var socket = context.WebSocket;//传入的context中有当前的web socket对象
- _sockets.Add(socket);//此处将web socket对象加入一个静态列表中
//进入一个无限循环,当web socket close是循环结束- while (true)
- {
- var buffer = new ArraySegment<byte>(new byte[]);
- var receivedResult = await socket.ReceiveAsync(buffer, CancellationToken.None);//对web socket进行异步接收数据
- if (receivedResult.MessageType == WebSocketMessageType.Close)
- {
- await socket.CloseAsync(WebSocketCloseStatus.Empty, string.Empty, CancellationToken.None);//如果client发起close请求,对client进行ack
- _sockets.Remove(socket);
- break;
- }
- if (socket.State == System.Net.WebSockets.WebSocketState.Open)
- {
- string recvMsg = Encoding.UTF8.GetString(buffer.Array, , receivedResult.Count);
- var recvBytes = Encoding.UTF8.GetBytes(recvMsg);
- var sendBuffer = new ArraySegment<byte>(recvBytes);
- foreach (var innerSocket in _sockets)//当接收到文本消息时,对当前服务器上所有web socket连接进行广播
- {
- if (innerSocket != socket)
- {
- await innerSocket.SendAsync(sendBuffer, WebSocketMessageType.Text, true, CancellationToken.None);
- }
- }
- }
- }
服务器端代码就绪,浏览器端如何去调用呢,继续看代码:
- var webSocket = new WebSocket("ws://localhost/api/chat?nickName=" + nickName.value);
- webSocket.onopen = function () {
- console.log("opened");
- }
- webSocket.onerror = function () {
- console.log("web socket error");
- }
- webSocket.onmessage = function (event) {
- console.log("web socket error");
- }
- self.webSocket.onclose = function () { console.log("closed"); }
这样就建立了一个web socket连接并能收到消息了,当然也会有发送消息的接口:
- webSocket.send(“Hello Web Socket”);
到这里,基于web socket的全双工通信机制已经建立好了。文中的demo是一个简易的聊天室程序。代码链接:https://github.com/lbwxly/WebSocketSample
补充:
HttpContext的AcceptWebSocketRequest方法只能接受一个函数确实有点不方便,也不利于封装与复用。因此为其添加了一个接受对象的重载extension方法,然后定义一个类WebSocketHandler来处理消息的收发和连接的关闭。详见上面的代码链接。
ASP.NET Web API上实现 Web Socket的更多相关文章
- ASP.NET Web API上实现 Web Socket - 转
1. 什么是Web Socket Web Socket是Html5中引入的通信机制,它为浏览器与后台服务器之间提供了基于TCP的全双工的通信通道.用以替代以往的LongPooling等comet st ...
- 在ASP.NET Core Web API上使用Swagger提供API文档
我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的API文档功能.当设置IISExpress的默认启动路由到Swagger的API文档页 ...
- 返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作
原文:返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, ...
- Core Web API上使用Swagger提供API文档
在ASP.NET Core Web API上使用Swagger提供API文档 我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的AP ...
- ASP.NET MVC Web API 学习笔记---Web API概述及程序示例
1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...
- 演示如何通过 web api 上传文件MVC40
演示如何通过 web api 上传文件WebApiWebFormHost/UploadFileController.cs /* * 通过 web api 上传文件 */ using System; u ...
- 基于SqlSugar的数据库访问处理的封装,在.net6框架的Web API上开发应用
我前面几篇随笔介绍了关于几篇关于SqlSugar的基础封装,已经可以直接应用在Winform项目开发上,并且基础接口也通过了单元测试,同时测试通过了一些Winform功能页面:本篇随笔继续深化应用开发 ...
- [Web API] 如何让 Web API 统一回传格式以及例外处理[转]
[Web API] 如何让 Web API 统一回传格式以及例外处理 前言 当我们在开发 Web API 时,一般的情况下每个 API 回传的数据型态或格式都不尽相同,如果你的项目从头到尾都是由你一个 ...
- [Web API] 如何让 Web API 统一回传格式以及例外处理
[Web API] 如何让 Web API 统一回传格式以及例外处理 前言 当我们在开发 Web API 时,一般的情况下每个 API 回传的数据型态或格式都不尽相同,如果你的项目从头到尾都是由你一个 ...
随机推荐
- Install mcrypt for php on Mac OSX 10.10 Yosemite for a Development Server
mcrypt is a file encryption method using secure techniques to exchange data. It is required for some ...
- Window.Open参数、返回值
一.window.open()支持环境: JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二.基本语法: window.open(pageURL,name, ...
- NSRange、NSPoint(CGPoint)、NSSize(CGSize)、NSRect(CGRect)
1.NSRange: typedef struct _NSRange { NSUInteger location; NSUInteger length; } NSRange; NSRange本身是系统 ...
- .net 自然排序方式
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...
- ORA-06550:line 1,column 7;PLS-00201:indentifer '存储过程' must be declared;...PL/SQL Statement ignored 问题
前段时间由于修改SMES系统,出现了一个问题. ORA-06550:line 1,column 7;PLS-00201:indentifer '存储过程' must be declared;...PL ...
- [转载]关于安装Android Studio的一些问题的解决方法
最近在研究Android编程,在Android Studio安装和使用时遇到了麻烦,从园子里找到了<关于安装Android Studio的一些问题的解决方法>的,很多问题找到了解决办法. ...
- C#快速排序算法基础入门篇
相信算法对于许多开发人员来说都是一大难点,之所以难,就像设计模式一样,许多人在阅读之后,没有很好地理解,也不愿意动手上机操作,只停留在理论的学习上面,随着时间推移就慢慢淡忘. 有些东西,你可以发明创造 ...
- Node.js 随记
http://nodejs.org/ 下载并安装 node.js 最新版本 运行cmd,输入npm install xxxxxx 回车,安装扩展模块,如:express,socket.io等 运行c ...
- 【WCF--初入江湖】04 WCF通信模式
04 WCF通信模式 WCF的通信模式有三种 [1]请求响应模式: 只能是客户端调用服务器; 客户端请求并等待服务器的响应后才继续执行后续操作(异步调用除外) [2]单工模式: 只能是客户端调用服务器 ...
- uva 11489
简单博弈 #include <cstdio> #include <cstdlib> #include <cmath> #include <map> #i ...