IE Chrome Firefox Safari Opera 10+16+11+6+12.10+ASP.NETWebAPI上实现WebSocket
1. 什么是Web Socket
2. Web Socket如何⼯作
Connect
Web Socket在建⽴之前需要先与后台服务器进⾏握⼿。具体来说通过如下Http请求:
GET /chat HTTP/1.1
Host: ample
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: example
后台服务器如果⽀持切换到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. 浏览器,服务器⽀持情况
参考,⽬前浏览器的⽀持情况如下:
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的消息收发函数(以前的 版本是接受⼀个实现特定接⼝的对象,新版改成了接受⼀个函数,总觉得怪怪的),代
码如下:
public async Task ProcessRequest(AspNetWebSocketContext context)
{
var socket = context.WebSocket;//传⼊的context中有当前的web socket对象
_sockets.Add(socket);//此处将web socket对象加⼊⼀个静态列表中
//进⼊⼀个⽆限循环,当web socket close是循环结束
while (true)
{websocket和socket
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);
console.log("opened");
}
console.log("web socket error");
}
console.log("web socket error");
}
lose = function () { console.log("closed"); }
这样就建⽴了⼀个web socket连接并能收到消息了,当然也会有发送消息的接⼝:
webSocket.send(“Hello Web Socket”);
补充:
HttpContext的AcceptWebSocketRequest⽅法只能接受⼀个函数确实有点不⽅便,也不利于封装与复⽤。因此为其添加了⼀个接受对象的重载extension⽅法,然后定义⼀个类WebSocketHandler来处理消息的收发和连接的关闭。详见上⾯的代码链接。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论