一步一步学WebSocket (一) 初识WebSocket

  众所周知,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服务器

  

时间: 2024-10-07 03:44:15

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

一步一步学WebSocket(二) 使用SuperWebSocket实现自己的服务端

上一篇文章,我们了解了客户端如何与服务器创建WebSocket连接.但是一个巴掌拍不响,既然是通信,就必然最少要有两个端.今天我们来看看c#如何用已有的框架实现一个WebSocket服务端. 在.Net Framework 4.5及以上版本中,微软为我们集成了WebSocket协议的基本实现.微软提供的WebSocket对象位于System.Net.WebSocket命名空间下,使用起来挺繁琐的,所以我选择了SuperWebSocket框架来简化开发的难度. SuperWebSocket框架可以

Rhythmk 一步一步学 JAVA (21) JAVA 多线程

1.JAVA多线程简单示例 1.1 .Thread  集成接口 Runnable 1.2 .线程状态,可以通过  Thread.getState()获取线程状态: New (新创建) Runnable (可以运行) Blocked  (被阻塞) Waiting  (等待) Timed waiting (计时等待) Terminated  (被终止) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

Rhythmk 一步一步学 JAVA (20) JAVA enum常用方法

JAVA 枚举定义常用方法: 1.static Enum valueOf(Class enum,String name) 返回指定name的枚举类型 2.Static Enum values[] 返回枚举常量集合 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

一步一步学solr:在开始前我们应该明白什么

我就用自己的项目来讲solr应用了,当然他的功能很多,大家可以看这里 http://my.oschina.net/fengnote/blog/288581 功能那是相当的多. solr可以理解为与应用分离的一个搜索服务,我们要搭建应用+搜索服务的关联配置实现部分业务. 我们的项目现在要改功能,一个内容发布系统,做一个站内搜索,原有的框架是SSI的,只把查询部分用solr来实现. 问题是: 我要查询一篇文章关联到N张表 我除了查询文章还要查询分类(也用solr实现) 新增.修改.删除文章/分类后要

Rhythmk 一步一步学 JAVA (22) JAVA 网络编程

1.获取主机信息 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test     public void GetDomainInfo() throws UnknownHostException {         String domain = "www.baidu.com";         InetAddress netAddress = InetAddress.getByName(domain);         // 获取

一步一步学ROP之linux_x64篇

一步一步学ROP之linux_x64篇 一.序 **ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术可以用来绕过现代操作系统的各种通用防御(比如内存不可执行和代码签名等).上次我们主要讨论了linux_x86的ROP攻击:<一步一步学ROP之linux_x86篇>,在这次的教程中我们会带来上一篇的补充以及linux_x64方面的ROP利用方法,欢迎大家继续学习. 另外文中涉及代码可在我的github下载:https://githu

一步一步学ios UITextView(多行文本框)控件的用法详解(五5.8)

本文转载至 http://wuchaorang.2008.blog.163.com/blog/static/48891852201232014813990/ 1.创建并初始化 创建UITextView的文件,并在.h文件中写入如下代码: [csharp] view plaincopy #import <UIKit/UIKit.h> @interface TextViewController : UIViewController <UITextViewDelegate> { UITe

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

[DG][三思笔记]一步一步学DataGuard 它有无数个名字,有人叫它dg,有人叫它数据卫士,有人叫它data guard,在oracle的各项特性中它有着举足轻理的地位,它就是(掌声)......................Oracle Data Guard.而对于我而言,我一定要亲切的叫它:DG(注:主要是因为打着方便). 不少未实际接触过dg的初学者可能会下意识以为dg是一个备份恢复的工具.我要说的是,这种形容不完全错,dg拥有备份的功能,某些情况下它甚至可以与primary数据库

一步一步学ZedBoard &amp; Zynq(七):制作ZedBoard上linux根文件系统(ramdisk)

一步一步学ZedBoard & Zynq(七):制作ZedBoard上linux根文件系统(ramdisk) 网址:http://xilinx.eetrend.com/blog/3935 Digilent的OOB设计给出了一个ZedBoard上完整的运行的linux系统所需要的所有文件,包括配置FPGA的bit文件. 配置ARM PS系统的First-Stage boot loader(FSBL)和引导linux需要的Second-Stage boot loader(SSBL).Linux内核z