众所周知,Http协议是无状态的,并且是基于Request/Response的方式与服务器进行交互,也就是我们常说的单工模式。但是随着互联网的发展,浏览器与服务端进行双向通信需求的增加,长轮询向服务器以获取最新数据并实现推送效果的方式已经越来越不能满足我们。Html5标准的制定,也为我们提供了浏览器与服务端的双工通信协议WebSocket。

  WebSocket协议的格式为 "ws://IP:Port" 或者“wss://IP:Port"。其中wss表示进行加密传输的websocket协议。

  WebSocket协议与传统的Socket协议一样,都需要进行“握手”。但是WebSocket的“握手”阶段是通过Http协议进行的,“握手”行为通过Request/Response的Header完成,只需要交换很少的数据,便可以创建基于TCP/IP协议的双工通道。下面我们来看一下Fiddler截取到的WebSocket握手请求

  

  通过Fiddler我们可以看到,在握手请求时,客户端向服务端发送了一个Get请求,并且在请求的头中增加了这么几个Key

  Origin:http://IP:Port 表示客户端的地址

  Connection:Upgrade / Upgrade:WebSocket 表示本次请求是要进行WebSocket的握手动作

  Sec-WebSocket-Version: 13 表示浏览器支持的WebSocket版本信息

  

  Sec-WebSocket-Key:     这是一个由客户端随机生成的字符串

  

  在服务器响应的握手信息中Sec-WebSocket-Accept:的值为服务器通过客户端Header的Sec-WebSocket-Key的值进行计算并加密的结果。

  

  并且服务器的响应状态为101  表示服务器端已经理解了客户端的需求,并且客户端需要根据Upgrade中的协议类型,切换为新的协议来完成后续的通信。

  这时候我们的TCP/IP双工通道就已经建立了,WebSocket协议就这么简单。

  说完理论知识了,我们来看如何在浏览器中使用WebSocket协议。

  

  

  最新的FireFox、Chrome、IE10及以上版本都已经支持了WebSocket协议。但是在使用它时,我们需要先检测浏览器是否支持WebSocket协议

  WebSocket对象位于 window对象下。我们可以通过以下代码检测浏览器对WebSocket的支持

  

  

if("WebSocket" in window)

if(window.WebSocket)

if("MozWebSocket" in window)

if(window.MozWebSocket)

  

  如果我们的浏览器支持WebSocket 那么我们就可以创建WebSocket的实例了。

  

var ws=new WebSocket("ws://localhost:2012");

var ws=new MozWebSocket("ws://localhost:2012);

  

  

  这里需要注意一下,当我们创建WebSocket的实例时,这个WebSocket实例就已经开始向服务器发起握手请求了,不需要我们手动打开连接。

  WebSocket对象也很简单,我们会常用到它的4个回调方法 onopen onclose onerror onmessage。他们触发的实际分别为 握手完成并创建TCP/IP通道后,断开连接后,发生错误时,接收到服务端消息时。

  另外我们还常常用到一个属性 readyState 用以检查连接状态,和一个函数 send() 向服务端发送数据。

  

  下面我们来完成一个完整的浏览器使用WebSocket的例子,这里需要服务端也支持WebSocket协议

  

  

  

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>WebSocket示例</title>
<script type="text/javascript">
var ws;//WebSocket对象
var wsUrl = "ws://localhost:2012";//支持WebSocket协议的服务器端地址 function connection() {
//判断该使用哪种WebSocket对象
if ("WebSocket" in window) {
ws = new WebSocket(wsUrl);
}
else if ("MozWebSocket" in window) {
ws = new MozWebSocket(wsUrl);
} else {
alert("当前浏览器不支持WebSocket"); } //注册各类回调
ws.onopen = function () {
alert("连接服务器成功");
} ws.onclose = function () {
alert("与服务器断开连接");
}
ws.onerror = function () {
alert("数据传输发生错误");
}
ws.onmessage = function (receiveMsg) {
alert(receiveMsg.data);
}
}
function sendMessage() {
//尝试向服务端发送消息 ws.send("Hello World"); } </script>
</head>
<body>
<input type="button" value="Connection" onclick="connection()" />
<input type="button" value="Send" onclick="sendMessage()" />
</body>
</html>

  

  

  

  完整示例代码在这里下载 示例代码的服务端是基于.Net Framework 4.5用VS2012开发的 因为服务器WebSocket框架的.NET 4.0版本有问题……

  下一篇文章我们会讲如何使用SuperWebSocket框架搭建我们自己的WebSocket服务器

  

一步一步学WebSocket (一) 初识WebSocket的更多相关文章

  1. 一步一步学ROP之linux_x64篇

    一步一步学ROP之linux_x64篇 一.序 **ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术可以用来绕过现代操作系统的各种通用防 ...

  2. 一步一步学ROP之linux_x86篇

    一步一步学ROP之linux_x86篇 作者:蒸米@阿里聚安全 ​ 一.序 ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术可以用来绕过 ...

  3. (转载)一步一步学Linq to sql系列文章

    现在Linq to sql的资料还不是很多,本人水平有限,如果有错或者误导请指出,谢谢. 一步一步学Linq to sql(一):预备知识 一步一步学Linq to sql(二):DataContex ...

  4. 一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计

    本帖最后由 xinxincaijq 于 2013-1-9 10:27 编辑 一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计 转自博客:http:// ...

  5. 一步一步学android控件(之十五) —— DegitalClock & AnalogClock

    原本计划DigitalClock和AnalogClock单独各一篇来写,但是想想,两个控件的作用都一样,就和在一起写一篇了. DegitalClock和AnalogClock控件主要用于显示当前时间信 ...

  6. 一步一步学Remoting系列文章

    转自:http://www.cnblogs.com/lovecherry/archive/2005/05/24/161437.html (原创)一步一步学Remoting之一:从简单开始(原创)一步一 ...

  7. 一步一步学android控件(之十六)—— CheckBox

    根据使用场景不同,有时候使用系统默认的CheckBox样式就可以了,但是有时候就需要自定义CheckBox的样式.今天主要学习如何自定义CheckBox样式.在CheckBox状态改变时有时需要做一些 ...

  8. 一步一步学Python(2) 连接多台主机执行脚本

    最近在客户现场,每日都需要巡检大量主机系统的备库信息.如果一台台执行,时间浪费的就太冤枉了. 参考同事之前写的一个python脚本,配合各主机上写好的shell检查脚本,实现一次操作得到所有巡检结果. ...

  9. 【DG】[三思笔记]一步一步学DataGuard

    [DG][三思笔记]一步一步学DataGuard 它有无数个名字,有人叫它dg,有人叫它数据卫士,有人叫它data guard,在oracle的各项特性中它有着举足轻理的地位,它就是(掌声)..... ...

随机推荐

  1. Python导入自定义包或模块

    一般我们会将自己写的 Python 模块与 Python 自带的模块分开存放以达到便于维护的目的. Python 运行环境在查找模块时是对 sys.path 列表进行遍历,如果我们想在运行环境中添加自 ...

  2. JE22环境安装配置(JDK/ANT/TOMCAT/ECLIPSE)

    文章中不涉及安装的均为解压即可直接使用的 1.安装JDK最新的J2EE安装会默认安装GlassFish,安装Java SDK就足够了,不是非要装JavaEE SDK,因为Tomcat的lib目录下,已 ...

  3. 坦克大战,看你能坚持几秒 ~~Duang~~Duang

    闲来无事,写了一个坦克大战的小游戏,打开页面就能看到源码,代码还没有来得及整理.大家闲来玩玩吧,看谁玩的时间长! http://xiaohaibaomu.com/home/index

  4. [DFNews] EnCase v7.08发布

    EnCase v7.08 近日正式发布,7.08增加了Evidence Processor Manager以及Evidence Processor,不仅可以在本地实现证据处理队列,也支持了通过网络进行 ...

  5. 【解决】若要使用报表生成器,必须在此计算机上安装 .Net Framework 3.5

    在报表库中试图通过点击菜单“在报表生成器中编辑”编辑报表时,会跳转到错误信息页面,提示: 若要使用报表生成器,必须在此计算机上安装 .Net Framework 3.5. 一般情况下并不是因为没有安装 ...

  6. SpringMVC国际化

    如何将我们网站的其它内容(如菜单.标题等)做国际化处理呢?这就是本篇要将的内容->国际化. 一.基于浏览器请求的国际化实现: 首先配置我们项目的springservlet-config.xml文 ...

  7. C++设计模式-Facade模式

    Facade模式 作用:为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 动机 将一个系统划分成为若干个子系统有利于降低系统的复杂性.一 ...

  8. Bootstrap框架(基础篇)

    本文引用慕课网http://www.imooc.com/learn/141  作者大漠  讲的很详细,我没有全篇都引用,其中很多是添加了自己的一些理解. Bootstrap框架是基于JQuery 所以 ...

  9. 用iptables 实现本地端口转发

    设定本机2121端口转发到21端口 iptables -t nat -A PREROUTING -p tcp -i eth0 -d -j DNAT --to iptables -t nat -I PO ...

  10. setFeatureInt、android 自定义标题栏

    Android 自带的toolbar 往往不能很好的的满足我们的个性化要求.因此我们经常使用自定的的标题栏.而Android系统本身也允许我们自定以标题栏. 记录一下,自定义标题栏常遇到的问题.先上效 ...