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的更多相关文章

  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. OC类的本质,深入探讨,load方法和initialize方法

    1:类的本质:类也是一种类,可以叫做类类,类对象,类类型: 2:类和对象在内存中分配问题(注意区分类的对象和类对象的概念) 类对象在内存中只有一份,且只加载一次,类对象中存放了类中定义的方法: 而成员 ...

  2. win8安装matlab7.0

    win8和win7下安装matlab7.0要注意许多地方,其实安装最新版一般都是没有问题的. 不过最新版太大,校园网下载太难,所以还是用7.0 基本上在百度经验上已经包括了大部分的注意事项了,可以参考 ...

  3. android手机推送视频到服务端

    项目需求,android手机向服务器推送视频.苦战几个星期终于实现,现记录下来以免以后忘记. 没做过Java,也没做过Android开发,只能现学现卖.在网上找了下搭建开发a  ndroid环境资料, ...

  4. python pip和easy_install使用方式(转载)

    easy_install 跟 pip 都是Python 的套件管理程式,有了它们,在使用 Python 开发程式的时候会带来不少方便. easy_install 和pip 有什麼不一样?据 pip 官 ...

  5. zju 1037 Gridland(找规律,水题)

    题目链接 多写几个案例,根据数据的奇偶性,就能找到规律了 #include<stdio.h> int main() { int t,n,m; double ans; scanf(" ...

  6. ios学习笔记block回调的应用(一个简单的例子)

    一.什么是Blocks      Block是一个C级别的语法以及运行时的一个特性,和标准C中的函数(函数指针)类似,但是其运行需要编译器和运行时支持,从ios4.0开始就很好的支持Block. 二. ...

  7. lintcode :Partition List 链表划分

    题目: 链表划分 给定一个单链表和数值x,划分链表使得所有小于x的节点排在大于等于x的节点之前. 你应该保留两部分内链表节点原有的相对顺序. 样例 给定链表 1->4->3->2-& ...

  8. tomcat源码导入eclipse

    1. 获取源代码 方式一:从官网http://tomcat.apache.org/download-70.cgi 直接下载,官网提供了Binary 和 Source Code两种下载方式,要研究tom ...

  9. linux上应用程序的执行机制

    linux上应用程序的执行机制 执行文件是如何在shell中被"执行"的.本文中尽可能少用一些源码,免得太过于无 聊,主要讲清这个过程,感兴趣的同学可以去查看相应的源码了解更多的信 ...

  10. JavaWeb项目开发案例精粹-第2章投票系统-004action层

    1. package com.sanqing.action; import java.util.UUID; import com.opensymphony.xwork2.ActionSupport; ...