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[1024]);
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, 0, 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 - 转的更多相关文章

  1. ASP.NET Web API上实现 Web Socket

    1. 什么是Web Socket Web Socket是Html5中引入的通信机制,它为浏览器与后台服务器之间提供了基于TCP的全双工的通信通道.用以替代以往的LongPooling等comet st ...

  2. 在ASP.NET Core Web API上使用Swagger提供API文档

    我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的API文档功能.当设置IISExpress的默认启动路由到Swagger的API文档页 ...

  3. 返璞归真 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 上传文件, ...

  4. Core Web API上使用Swagger提供API文档

    在ASP.NET Core Web API上使用Swagger提供API文档   我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的AP ...

  5. ASP.NET MVC Web API 学习笔记---Web API概述及程序示例

    1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...

  6. 演示如何通过 web api 上传文件MVC40

    演示如何通过 web api 上传文件WebApiWebFormHost/UploadFileController.cs /* * 通过 web api 上传文件 */ using System; u ...

  7. 基于SqlSugar的数据库访问处理的封装,在.net6框架的Web API上开发应用

    我前面几篇随笔介绍了关于几篇关于SqlSugar的基础封装,已经可以直接应用在Winform项目开发上,并且基础接口也通过了单元测试,同时测试通过了一些Winform功能页面:本篇随笔继续深化应用开发 ...

  8. [Web API] 如何让 Web API 统一回传格式以及例外处理[转]

    [Web API] 如何让 Web API 统一回传格式以及例外处理 前言 当我们在开发 Web API 时,一般的情况下每个 API 回传的数据型态或格式都不尽相同,如果你的项目从头到尾都是由你一个 ...

  9. [Web API] 如何让 Web API 统一回传格式以及例外处理

    [Web API] 如何让 Web API 统一回传格式以及例外处理 前言 当我们在开发 Web API 时,一般的情况下每个 API 回传的数据型态或格式都不尽相同,如果你的项目从头到尾都是由你一个 ...

随机推荐

  1. CSS字体超出两行省略

    text-overflow: -o-ellipsis-lastline;overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-w ...

  2. Expo大作战(二十九)--expo sdk api之registerRootComponent(注册跟组件),ScreenOrientation(屏幕切换),SecureStore,

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  3. exception is feign.RetryableException: Connection refused (Connection refused) executing GET http://......

    2018-03-23 10:00:58.430 ERROR 31889 --- [nio-4321-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Se ...

  4. python 遇到的小坑

    由于前端资源紧缺,我的后端系统迟迟等不来它的前端,没办法只好自己来写了.从html,js入门学起,然后照着vue.js的官方教程写了几个实例,从github上clone了一个不错的vue.js模版,填 ...

  5. Spring Boot 技术总结

    Spring Boot(一):入门篇 Spring Boot(二):Web 综合开发 Spring Boot(三):Spring Boot 中 Redis 的使用 Spring Boot(四):Thy ...

  6. python第四十二天 socket ---ssh

    用scoket 写一个简版的ssh 服务端: #!usr/bin/env python #-*-coding:utf-8-*- # Author calmyan import socket,os s= ...

  7. 使用python3.6和django1.9的xadmin 遇到坑,__unicode__()和__str__()

    原因:python版本为3.6,Python3.X的版本不可使用__unicode__()(python2.x可用),应改为__str__().

  8. mac系统如何在当前目录下打开终端

    给大家推荐一个好用的终端工具 Go2Shell:https://itunes.apple.com/cn/app/go2shell/id445770608?mt=12 在没有这个工具之前 找了好多在当前 ...

  9. Java设计模式之九 ----- 解释器模式和迭代器模式

    前言 在上一篇中我们学习了行为型模式的责任链模式(Chain of Responsibility Pattern)和命令模式(Command Pattern).本篇则来学习下行为型模式的两个模式, 解 ...

  10. 用智能TFT液晶模块这种串口屏做产品界面设计太简单了,大大的节省了开发时间

    随着科技的发展,TFT液晶显示屏在我们日常中可以随处可见. 工业设备上的显示也逐渐由段式显示.黑白显示转向彩色的TFT液晶显示屏. 普通的TFT液晶显示屏由于开发起来比较麻烦, 需要嵌入式工程时写程序 ...