赵工的个人空间


专业技术部分转网页计算转业余爱好部分


  网站建设

首页 > 专业技术 > 网站建设 > HTML5 WebSocket通信
HTML5 WebSocket通信

HTML5提供了一种全新的双工通信模块WebSocket。WebSocket是一种基于TCP连接的通信技术,主要在浏览器和服务器之间提供一种双向通信的解决方案。通过简单的握手协议,建立一个长连接,然后按照协议的规则进行数据的传输。
WebSocket包含两方面的内容,一方面是WebSocket协议,主要是在浏览器与服务器之间建立通信;另一方面是浏览器中的WebSocket编程接口,用于网页的JavaScript脚本编程。
WebSocket协议可以使用任何服务器端的编程语言来实现,WebSocket编程接口主要用于客户端的JavaScript编程开发。
WebSocket首先是降低了服务器的网络开销,每次HTTP请求都会包含大约800B报头信息,而WebSocket每个消息都是一个WebSocket帧,仅有2B的开销。WebSocket使用HTTP_CONNECT代理协议,不受防火墙限制。开发人员只与编程接口打交道,可以不了解通信协议细节就可以开发应用。

1.WebSocket握手协议:

WebSocket规范还没有正式形成,版本更新很快,draft-ietf-hybi-thewebsocketprotocol-10是最新的Chrome和Firefox浏览器支持的协议版本。
从浏览器到服务器:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection:Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 8

从服务器到浏览器:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection:Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
首先从浏览器向服务器发送的HTTP协议头中,包含的Upgrade: websocket表示连接协议升级到WebSocket协议,其他内容就是WebSocket协议所需要的相关握手信息。服务器解析这些协议,并返回一个密钥给浏览器,表明同意建立WebSocket连接。
一旦连接建立,浏览器和服务器就可以基于双工通信信道相互传递WebSocket帧消息。网络中,每个帧消息都是以0x00开头,以0xFF结尾,中间采用UTF-8编码格式。

2.WebSocket编程接口:

[Constructor (DOMString url, optional DOMString protocols), Constructor (DOMString url, optional DOMString[] protocals)]
interface WebSocket : EventTarget {
   readonly attribute DOMString url;
   //就绪状态
   const unsigned short CONNECTING=0;
   const unsigned short OPEN=1;
   const unsigned short CLOSING=2;
   const unsigned short CLOSED=3;
   readonly attribute unsigned short readyState;
   readonly attribute unsigned long bufferedAmount;
   //网络
   [TreatNonCallableAsNull] attribute Function? onopen;
   [TreatNonCallableAsNull] attribute Function? onerror;
   [TreatNonCallableAsNull] attribute Function? onclose;
   readonly attribute DOMString extensions;
   readonly attribute DOMString protocol;
   void close ([Clamp] optional unsigned short code, optional DOMString reason);
   //消息
   [TreatNonCallableAsNull] attribute Function? onmessage;
   attribute DOMString binaryType;
   void send (DOMString data);
   void send (ArrayBuffer data);
   void send (Blob data);
};

1)WebSocket构造函数:

WebSocket的构造函数WebSocket(url,protocols)带有一个或两个参数,可以使用该构造函数建立一个WebSocket的连接对象。方法为:
var socket=new WebSocket(url,protocols);
其中,url指定了要连接的URL地址,该连接地址是以“ws://”和“wss://”开始的,分别表示常规的WebSocket连接和安全的WebSocket连接。Protocols表示建立连接使用的协议,是可选参数,可以是一个字符串或字符串数组。数组中的每一个字符串均为子协议名称,只有服务器选择了其中的一个子协议,连接才会建立。

2)WebSocket属性:6个属性

·URL:获取完成构造函数解析的结果地址,只读属性。
·readyState:获取连接的状态,只读属性。连接状态有4个值:

状态

说明

CONNECTING

0

连接尚未构建

OPEN

1

WebSocket连接已经建立,并且可以进行通讯

CLOSING

2

正在关闭握手连接

CLOSED

3

连接已经关闭,或连接没有打开

当WebSocket的连接对象创建完成时,readyState值被设置为CONNECTING(0)。
·bufferedAmount:获取发送前缓冲的尚未发送的应用程序的字节数,只读属性。指的是发送队列中某个应用数据已经开始发送,但尚未传送到网络上的部分。
·extensions:获取服务器选择的扩展。该属性值初始化的时候是一个空的字符串,但在WebSocket连接建立之后,值可能会发生变化。只读属性。
·protocol:获取服务器选择的子协议。该属性初始化的时候是一个空的字符串,但在WebSocket连接建立之后,值可能会发生变化。只读属性。
·binary/Type:获取/设置二进制类型。当WebSocket的连接对象创建完成时,binary/Tyoe的值被初始化为blob。

3)WebSocket方法:两个方法

·send():用来发送消息。用法为:
socket.send(data);
该方法中有一个参数data,表示发送的数据。该数据类型可以是字符串数据、Blob对象或ArrayBuffer对象等。
·close():用来关闭连接。用法为:
socket.close();
在执行关闭操作时,如果readyState属性是在CLOSING或CLOSED状态,则什么都不做。否则会设置readySyate属性为CLOSING,并触发close事件。

4)WebSocket事件:4个事件

·message:当浏览器收到来自服务器的消息时触发的事件。
·open:当WebSocket连接已经建立,并且可以进行通信时触发的事件,即readyState的值为OPEN时触发。
·close:当关闭连接时触发的事件,即readyState的值为CLOSING时触发。
·error:当有任何的错误产生时触发的事件。

5)从协议反馈的过程:

当WebSocket连接已经建立后,浏览器需要依次执行下列步骤:
首先,更改readyState属性的值为OPEN;其次,更新extensions的值和protocols的值(如果不为空时更新);接着,根据服务器反馈的信息完成握手协议;最后,触发open事件。
当WebSocket的消息事件收到数据时,浏览器需要依次执行如下步骤:
首先,判断readyState属性的值,如果不是OPEN,则中止后续的步骤;其次,使用MessageEvent接口,并确保message消息事件不起泡、不取消并且没有预设动作;接着,初始化消息事件接口的origin属性值为WebSocket连接对象的URL属性值;之后,根据数据的类型初始化消息事件接口的data属性值为相应类型的数据;最后,通过WebSocket连接对象调用message事件。

3.WebSocket编程:

1)检测浏览器的支持情况:

使用WebSocket之前,需要检测浏览器是否支持该功能。检测方法为:
if (!window.WebSocket) {
   console.log("使用的浏览器支持WebSocket,可以尝试连接到服务器。");
} else {
   console.log("使用的浏览器不支持WebSocket,清选择其他浏览器。");
}

2)建立连接:

WebSocket建立连接只需要提供一个URL地址,创建一个新的WebSocket实例即可。该URL地址是以“ws://”和“wss://”开始的。示例:
socket=new WebSocket("ws://localhost:8090/chat");

3)添加状态监听事件和消息监听事件:

提供给WebSocket对象添加监听事件,可以及时获取连接状态和接收消息。添加事件后,只需要等待事件的发送,而不用再去轮询。下面代码为WebSocket添加了4个监听事件:
socket.onopen=function() {
   console.log("连接已经建立");
}
socket.onclose=function() {
   console.log("连接已经关闭");
}
socket.onerror=function() {
   console.log("发送错误");
}
socket.onmessage=function(evt) {
   console.log("收到来自服务器的消息:"+evt.data);
}

4)发送信息:

当WebSocket对象处于打开状态时,可以响应send()方法向服务器端发送数据。发送信息只需要如下操作:
socket.send("Hello,World!");

5)关闭连接:

当需要关闭连接时,可以直接调用WebSocket对象的close()方法。在浏览器发送消息或接收消息之后,WebSocket对象是不会主动关闭连接的,只有调用了close()方法,浏览器才会主动关闭连接。
socket.close();

4.示例:聊天室,单击连接按钮建立连接,显示聊天室产生的消息,发送聊天消息

1)服务器端的部署:

一个完整的WebSocket应用,需要由服务器提供一个WebSocket服务,该服务可以使用多种语言来开发。服务器端的实现需要参考WebSocket协议。

2)设计聊天室页面:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>WebSocket</title>
  <link rel="stylesheet" href="websocket.css">
  <script src="websocket.js"></script>
</head>
<body>
<form id="form1" runat="server">
   <h1>WebSocket聊天室</h1>
   <div>
   <input type="button" id="connectButton" value="连接" onclick="connection()" />
   连接状态:<span id="state"></span>
   </div>
   <div id="logContainer" class="container"></div>
   <div>用户
   <input type="text" id="txtName" value="Zhao" size="6" />
   <input type="text" id="data" size="40" />
   <button id="sendBut" type="button" onclick="sendData()">发送</button>
   </div>
</form>
</body>
</html>

3)WebSocket代码:

var ws;
var SocketCreated=false;
window.onload=function() {
   if (!window.WebSocket) {
      Log("使用的浏览器支持WebSocket,可以尝试连接到服务器。","OK");
   } else {
      Log("使用的浏览器不支持WebSocket,清选择其他浏览器。","ERROR");
   }
}
function connection() {
   if (SocketCreated&&(ws.readyState==0||ws.readyState==1)) {
        ws.close();
   } else {
        Log("准备连接到聊天室……");
        ws=new WebSocket("ws://localhost:8090/chat");
        SocketCreated=true;
        document.getElementById("connectButton").value="断开";
        socket.onopen=function() {
          Log("连接已经建立","OK");
          ws.send("欢迎"+document.getElementById("txtName").value+"来到聊天室!");
        }
        socket.onclose=function() {
          Log("连接关闭","ERROR");
          document.getElementById("connectButton").value="连接";
        }
        socket.onerror=function() {
          Log("WebSocket错误","ERROR");
        }
        socket.onmessage=function(event) {
          Log(event.data);
        }
   }
}

4)其中使用的自定义函数代码:

function sendData() {
   var obj=document.getElementById("data");
   if (obj.value!="") {
        ws.send(document.getElementById("txtName").value+"说:"+obj.value);
        Obj.value="";
   }
}
function Log(Text,messageType) {
   if (messageType=="OK") Text="<span style='color:green;'>"+Text+"</span>";
   if (messageType=="ERROR") Text="<span style='color:red;'>"+Text+"</span>";
   var logContainer=document.getElementById("logContainer");
   logContainer.innerHTML+=Text+"<br />";
   logContainer.scrollTop=logContainer,scrollHeight;
}

Copyright@dwenzhao.cn All Rights Reserved   备案号:粤ICP备15026949号
联系邮箱:dwenzhao@163.com  QQ:1608288659