Home >Web Front-end >HTML Tutorial >[Transfer] Build real-time web applications using HTML5 WebSocket_html/css_WEB-ITnose
HTML5 WebSocket introduction and practical exercises
This article mainly introduces the principles of HTML5 WebSocket and the revolutionary benefits it brings to real-time Web development Innovation, and fully demonstrates the power and ease of use of WebSocket through a case of WebSocket server and client.
As the next generation of web standards, HTML5 has many compelling new features, such as Canvas, local storage, multimedia programming interface, WebSocket, and more. Among them, WebSocket, known as the "TCP of the Web," particularly attracts the attention of developers. The emergence of WebSocket makes it possible for browsers to provide support for Socket, thereby providing a two-way channel based on TCP connections between the browser and the server. Web developers can easily use WebSocket to build real-time web applications, and developers now have another magic weapon in their hands. This article first introduces the basic concepts of HTML5 WebSocket and the problems this specification attempts to solve, and then introduces the basic principles and programming interfaces of WebSocket. Next, we will use a simple case to demonstrate how to implement a WebSocket application, and show how WebSocket can achieve the perfect unity of powerful functions and easy-to-use programming. Finally, the current status, limitations and future prospects of WebSocket support in mainstream browsers are introduced.
The information interaction process of Web applications is usually that the client sends a request through the browser, and the server processes the request after receiving and reviewing it and returns the result to the client. , and then the client browser presents the information. This mechanism is fine for applications where information changes are not particularly frequent, but for applications with high real-time requirements, such as online games, online securities, and equipment monitoring. , online news broadcasts, RSS subscription push, etc., when the client browser is ready to present this information, this information may be out of date on the server side. Therefore, keeping client-side and server-side information synchronized is a key element of real-time web applications, and it is also a difficult problem for web developers. Before the WebSocket specification came out, developers who wanted to implement these real-time Web applications had to adopt some compromise solutions, the most commonly used of which were polling and Comet technology, and Comet technology is actually an improvement of polling technology. It can be subdivided into two implementation methods, one is the long polling mechanism, and the other is called streaming technology. Below we briefly introduce these technologies:
Polling :
This is the earliest solution to implement real-time web applications. The client sends requests to the server at certain intervals, and maintains synchronization between the client and the server through frequent requests. The biggest problem with this synchronization scheme is that when the client initiates a request to the server at a fixed frequency, the data on the server side may not be updated, which will cause a lot of unnecessary network transmission, so this is a very inefficient real-time plan.
Long polling:
Long polling is an improvement and enhancement of scheduled polling, with the purpose of reducing invalid network transmission. When there is no data update on the server side, the connection will be maintained for a period of time until the data or status changes or the time expires. This mechanism reduces invalid interactions between the client and the server. Of course, if the data on the server changes very frequently, this mechanism will not substantially improve performance compared to scheduled polling.
Streaming:
The streaming technology solution usually uses a hidden window on the client page to issue a long connection request to the server. After receiving this request, the server responds and continuously updates the connection status to ensure that the connection between the client and the server does not expire. Through this mechanism, server-side information can be continuously pushed to the client. This mechanism has some problems with user experience. Different solutions need to be designed for different browsers to improve user experience. At the same time, this mechanism is a great test for server-side resources when concurrency is relatively large.
Based on these solutions, you will find that the so-called real-time technologies we are currently using are not real real-time technologies. They are just using Ajax to simulate real-time effects. Each time the client and The server-side interaction is a process of HTTP request and response, and each HTTP request and response carries complete HTTP header information, which increases the amount of data transmitted each time, and in these solutions the client Both the server-side programming and the server-side programming implementation are relatively complex. In actual applications, in order to simulate a more realistic real-time effect, developers often need to construct two HTTP connections to simulate the two-way communication between the client and the server. One connection is used to process the client. For end-to-server data transmission, one connection is used to handle data transmission from server to client, which inevitably increases the complexity of programming implementation, increases the load on the server, and restricts the scalability of the application system.
HTML5 WebSocket is designed to replace polling and Comet technology, so that client browsers have real-time communication capabilities like desktop systems under a C/S architecture. The browser sends a request to the server to establish a WebSocket connection through JavaScript. After the connection is established, the client and server can directly exchange data through the TCP connection. Because the WebSocket connection is essentially a TCP connection, it has great performance advantages compared with polling and Comet technologies in terms of data transmission stability and data transmission volume. The Websocket.org website conducted a detailed test and comparison of the traditional polling method and the WebSocket calling method. A simple Web application was implemented using the polling method and the WebSocket method respectively. Here is a quote from their test results:
Figure 1. Network load comparison chart between polling and WebSocket implementationsIt can be clearly seen from this figure that when the traffic and load increase, the WebSocket solution The traditional Ajax polling scheme has great performance advantages. This is why we believe WebSocket is the solution of choice for real-time web applications in the future.
The WebSocket protocol is essentially a TCP-based protocol. In order to establish a WebSocket connection, the client browser must first initiate an HTTP request to the server. This request is different from a normal HTTP request and contains some additional header information, including the additional header information "Upgrade: WebSocket" Indicates that this is an HTTP request to apply for a protocol upgrade. The server parses these additional header information and then generates response information and returns it to the client. The WebSocket connection between the client and the server is established, and both parties can communicate freely through this connection channel. information, and this connection will continue to exist until either the client or the server actively closes the connection.
Let’s introduce the WebSocket specification in detail. Since this specification is still in the draft stage and the version changes quickly, we choose the draft-hixie-thewebsocketprotocol-76 version to describe the WebSocket protocol. . Because this version is currently well supported on some mainstream browsers such as Chrome, FireFox, and Opera, if you are referring to a newer version, the content may be slightly different.
A typical example of WebSocket initiating a request and getting a response looks as follows:
Listing 1. WebSocket handshake protocol
<strong>客户端到服务端:</strong> GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Upgrade: WebSocket Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5 Origin: http://example.com [8-byte security key] <strong>服务端到客户端:</strong>HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade WebSocket-Origin: http://example.com WebSocket-Location: ws://example.com/demo [16-byte hash response]
These requests are very similar to normal HTTP requests. Similar, but some of the content is closely related to the WebSocket protocol. We need to briefly introduce these request and response information. "Upgrade:WebSocket" means that this is a special HTTP request. The purpose of the request is to upgrade the communication protocol between the client and the server from the HTTP protocol to the WebSocket protocol. The information requested from the client to the server contains header information such as "Sec-WebSocket-Key1", "Sec-WebSocket-Key2" and "[8-byte securitykey]". This is the handshake information that the client browser needs to provide to the server. The server parses these header information and generates a 16-bit security key based on this information during the handshake process and returns it to the client to indicate that the server has obtained Accepts the client's request and agrees to create a WebSocket connection. Once the connection is established, the client and server can transmit data in both directions through this channel.
In the actual development process, in order to use the WebSocket interface to build Web applications, we first need to build a server that implements the WebSocket specification. The server-side implementation is not restricted by the platform and development language, and only needs to comply with the WebSocket specification. That’s it. There are already some relatively mature WebSocket server-side implementations, such as:
If the above WebSocket If the server-side implementation cannot meet your business needs, developers can implement a server themselves according to the WebSocket specification. In the "WebSocket Practical Combat" section, we will use the C# language on the Microsoft .NET platform to build a simple WebSocket server, and then build a simple real-time chat system.
The previous section introduced the WebSocket specification, which mainly introduced the WebSocket handshake protocol. The handshake protocol is usually an issue we need to consider when building a WebSocket server-side implementation and providing browser WebSocket support. The WebSocket JavaScript client interface for web developers is very simple. The following is the definition of the WebSocket JavaScript interface:
Listing 2. WebSocket JavaScript definition
[Constructor(in DOMString url, in optional DOMString protocol)] interface WebSocket { readonly attribute DOMString URL; // ready state const unsigned short CONNECTING = 0; const unsigned short OPEN = 1; const unsigned short CLOSED = 2; readonly attribute unsigned short readyState; readonly attribute unsigned long bufferedAmount; //networking attribute Function onopen; attribute Function onmessage; attribute Function onclose; boolean send(in DOMString data); void close(); }; WebSocket implements EventTarget;
其中 URL 属性代表 WebSocket 服务器的网络地址,协议通常是”ws”,send 方法就是发送数据到服务器端,close 方法就是关闭连接。除了这些方法,还有一些很重要的事件:onopen,onmessage,onerror 以及 onclose。我们借用 Nettuts 网站上的一张图来形象的展示一下 WebSocket 接口:
图 2. WebSocket JavaScript 接口下面是一段简单的 JavaScript 代码展示了怎样建立 WebSocket 连接和获取数据:
清单 3. 建立 WebSocket 连接的实例 JavaScript 代码
var wsServer = 'ws://localhost:8888/Demo'; var websocket = new WebSocket(wsServer); websocket.onopen = function (evt) { onOpen(evt) }; websocket.onclose = function (evt) { onClose(evt) }; websocket.onmessage = function (evt) { onMessage(evt) }; websocket.onerror = function (evt) { onError(evt) }; function onOpen(evt) { console.log("Connected to WebSocket server."); } function onClose(evt) { console.log("Disconnected"); } function onMessage(evt) { console.log('Retrieved data from server: ' + evt.data); } function onError(evt) { console.log('Error occured: ' + evt.data); }
下面是主流浏览器对 HTML5 WebSocket 的支持情况:
Chrome | Supported in version 4+ |
Firefox | Supported in version 4+ |
Internet Explorer | Supported in version 10+ |
Opera | Supported in version 10+ |
Safari | Supported in version 5+ |
这一节里我们用一个案例来演示怎么使用 WebSocket 构建一个实时的 Web 应用。这是一个简单的实时多人聊天系统,包括客户端和服务端的实现。客户端通过浏览器向聊天服务器发起请求,服务器端解析客户端发出的握手请求并产生应答信息返回给客户端,从而在客户端和服务器之间建立连接通道。服务器支持广播功能,每个聊天用户发送的信息会实时的发送给所有的用户,当用户退出聊天室时,服务器端需要清理相应用户的连接信息,避免资源的泄漏。以下我们分别从服务器端和客户端来演示这个 Web 聊天系统的实现,在实现方式上我们采用了 C# 语言来实现 WebSocket 服务器,而客户端是一个运行在浏览器里的 HTML 文件。
这个聊天服务器的实现和基于套接字的网络应用程序非常类似,首先是服务器端要启动一个套接字监听来自客户端的连接请求,关键的区别在于 WebSocket 服务器需要解析客户端的 WebSocket 握手信息,并根据 WebSocket 规范的要求产生相应的应答信息。一旦 WebSocket 连接通道建立以后,客户端和服务器端的交互就和普通的套接字网络应用程序是一样的了。所以在下面的关于 WebSocket 服务器端实现的描述中,我们主要阐述 WebSocket 服务器怎样处理 WebSocket 握手信息,至于 WebSocket 监听端口的建立,套接字信息流的读取和写入,都是一些常用的套接字编程的方式,我们就不多做解释了,您可以自行参阅本文的附件源代码文件。
在描述 WebSocket 规范时提到,一个典型的 WebSocket Upgrade 信息如下所示:
GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Upgrade: WebSocket Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5 Origin: http://example.com [8-byte security key]
其中 Sec-WebSocket-Key1,Sec-WebSocket-Key2 和 [8-byte security key] 这几个头信息是 WebSocket 服务器用来生成应答信息的来源,依据draft-hixie-thewebsocketprotocol-76 草案的定义,WebSocket 服务器基于以下的算法来产生正确的应答信息:
至此,客户端和服务器的 WebSocket 握手就完成了,WebSocket 通道也建立起来了。下面首先介绍一下服务器端实现是如何根据用户传递的握手信息来生成网络字节数组的。.NET 平台提供了很方便的对字符串,数值以及数组操作的函数,所以生成字节数组的方法还是非常简单明了的,代码如下:
清单 4. 生成网络字节数组的代码
private byte[] BuildServerPartialKey(string clientKey) { string partialServerKey = ""; byte[] currentKey; int spacesNum = 0; char[] keyChars = clientKey.ToCharArray(); foreach (char currentChar in keyChars) { if (char.IsDigit(currentChar)) partialServerKey += currentChar; if (char.IsWhiteSpace(currentChar)) spacesNum++; } try { currentKey = BitConverter.GetBytes((int)(Int64.Parse(partialServerKey) / spacesNum)); if (BitConverter.IsLittleEndian) Array.Reverse(currentKey); } catch { if (currentKey!= null) Array.Clear(currentKey, 0, currentKey.Length); } return currentKey; }
得到网络字节数组以后,服务器端生成 16 位安全密钥的方法如下所示:
清单 5. 生成 16 位安全密钥的代码
private byte[] BuildCompleteServerKey(byte[] serverKey1, byte[] serverKey2, byte[] last8Bytes) { byte[] concatenatedKeys = new byte[16]; Array.Copy(serverKey1, 0, concatenatedKeys, 0, 4); Array.Copy(serverKey2, 0, concatenatedKeys, 4, 4); Array.Copy(last8Bytes, 0, concatenatedKeys, 8, 8); System.Security.Cryptography.MD5 MD5Service = System.Security.Cryptography.MD5.Create(); return MD5Service.ComputeHash(concatenatedKeys); }
整个实现是非常简单明了的,就是将生成的网络字节数组和客户端提交的头信息里的 [8-byte security key] 合并成一个 16 位字节数组并用 MD5 算法加密,然后将生成的安全密钥作为应答信息返回给客户端,双方的 WebSocekt 连接通道就建立起来了。实现了 WebSocket 握手信息的处理逻辑,一个具有基本功能的 WebSocket 服务器就完成了。整个 WebSocket 服务器由两个核心类构成,一个是 WebSocketServer,另外一个是 SocketConnection,出于篇幅的考虑,我们不介绍每个类的属性和方法了,文章的附件会给出详细的源代码,有兴趣的读者可以参考。
服务器刚启动时的画面如下:
图 3. WebSocket 服务器刚启动的画面客户端可以依据这个信息填写聊天服务器的连接地址,当有客户端连接到聊天服务器上时,服务器会打印出客户端和服务器的握手信息,每个客户的聊天信息也会显示在服务器的界面上,运行中的聊天服务器的界面如下:
图 4. 有客户端连接到 WebSocket 服务器的以上我们简单描述了实现一个 WebSocket 服务器的最基本的要素,下一节我们会描述客户端的实现。
客户端的实现相对于服务器端的实现来说要简单得多了,我们只需要发挥想象去设计 HTML 用户界面,然后呼叫 WebSocket JavaScript 接口来和 WebSocket 服务器端来交互就可以了。当然别忘了使用一个支持 HTML5 和 WebSocket 的浏览器,在笔者写这篇文章的时候使用的浏览器是 Firefox。客户端的页面结构是非常简洁的,初始运行界面如下:
图 5. 聊天室客户端初始页面当页面初次加载的时候,首先会检测当前的浏览器是否支持 WebSocket 并给出相应的提示信息。用户按下连接按钮时,页面会初始化一个到聊天服务器的 WebSocekt 连接,初始化成功以后,页面会加载对应的 WebSocket 事件处理函数,客户端 JavaScript 代码如下所示:
清单 6. 初始化客户端 WebSocket 对象的代码
function ToggleConnectionClicked() { if (SocketCreated && (ws.readyState == 0 || ws.readyState == 1)) { ws.close(); } else { Log("准备连接到聊天服务器 ..."); try { ws = new WebSocket("ws://" + document.getElementById("Connection").value); SocketCreated = true; } catch (ex) { Log(ex, "ERROR"); return; } document.getElementById("ToggleConnection").innerHTML = "断开"; ws.onopen = WSonOpen; ws.onmessage = WSonMessage; ws.onclose = WSonClose; ws.onerror = WSonError; } }; function WSonOpen() { Log("连接已经建立。", "OK"); $("#SendDataContainer").show("slow"); }; function WSonMessage(event) { Log(event.data); }; function WSonClose() { Log("连接关闭。", "ERROR"); document.getElementById("ToggleConnection").innerHTML = "连接"; $("#SendDataContainer").hide("slow"); }; function WSonError() { Log("WebSocket错误。", "ERROR"); };
当用户按下发送按钮,客户端会调用WebSocket对象向服务器发送信息,并且这个消息会广播给所有的用户,实现代码如下所示:
function SendDataClicked() { if (document.getElementById("DataToSend").value != "") { ws.send(document.getElementById("txtName").value + "说 :\"" + document.getElementById("DataToSend").value + "\""); document.getElementById("DataToSend").value = ""; } };
如果有多个用户登录到聊天服务器,客户端页面的运行效果如下所示:
图 6. 聊天客户端运行页面至此我们已经完成了一个完整的 WebSocket 客户端实现,用户可以体验一下这个聊天室的简单和快捷,完全不用考虑页面的刷新和繁琐的 Ajax 调用,享受桌面程序的用户体验。WebSocket 的强大和易用可见一斑,您完全可以在这个基础上加入更多的功能,设计更加漂亮的用户界面,切身体验 WebSocket 的震撼力。完整的客户端代码请参阅附件提供的源代码。
WebSocket 的优点已经列举得很多了,但是作为一个正在演变中的 Web 规范,我们也要看到目前用 Websocket 构建应用程序的一些风险。首先,WebSocket 规范目前还处于草案阶段,也就是它的规范和 API 还是有变动的可能,另外的一个风险就是微软的 IE 作为占市场份额最大的浏览器,和其他的主流浏览器相比,对 HTML5 的支持是比较差的,这是我们在构建企业级的 Web 应用的时候必须要考虑的一个问题。
本文介绍了 HTML5 WebSocket 的横空出世以及它尝试解决的的问题,然后介绍了 WebSocket 规范和 WebSocket 接口,以及和传统的实时技术相比在性能上的优势,并且演示了怎样使用 WebSocket 构建一个实时的 Web 应用,最后我们介绍了当前的主流浏览器对 HTML5 的支持情况和 WebSocket 的局限性。不过,我们应该看到,尽管 HTML5 WebSocket 目前还有一些局限性,但是已经是大势所趋,微软也明确表达了未来对 HTML5 的支持,而且这些支持我们可以在 Windows 8 和 IE10 里看到,我们也在各种移动设备,平板电脑上看到了 HTML5 和 WebSocket 的身影。WebSocket 将会成为未来开发实时 Web 应用的生力军应该是毫无悬念的了,作为 Web 开发人员,关注 HTML5,关注 WebSocket 也应该提上日程了,否则我们在新一轮的软件革新的浪潮中只能做壁上观了。
转自 http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/
new-source.zip | 94KB |