WebSocket入门

WebSocket
前言
  WebSocket是HTML5的重要特性,它实现了基于浏览器的远程socket,它使浏览器和服务器能够进行全双工通讯,许多浏览器(Firefox、Google Chrome和Safari)都已对此作了支持。javascript

  在WebSocket出现以前,为了实现即时通讯,采用的技术都是“轮询”,即在特定的时间间隔内,由浏览器对服务器发出HTTP Request,服务器在收到请求后,返回最新的数据给浏览器刷新,“轮询”使得浏览器须要对服务器不断发出请求,这样会占用大量带宽。 html

  WebSocket采用了一些特殊的报头,使得浏览器和服务器只须要作一个握手的动做,就能够在浏览器和服务器之间创建一条链接通道。且此链接会保持在活动状态,你可使用JavaScript来向链接写入或从中接收数据,就像在使用一个常规的TCP Socket同样。它解决了Web实时化的问题,相比传统HTTP有以下好处:java

  • 一个Web客户端只创建一个TCP链接
  • Websocket服务端能够推送(push)数据到web客户端.
  • 有更加轻量级的头,减小数据传送量

WebSocket URL的起始输入是ws://或是wss://(在SSL上)。一个带有特定报头的HTTP握手被发送到了服务器端,接着在服务器端或是客户端就能够经过JavaScript来使用某种套接口(socket),这一套接口可被用来经过事件句柄异步地接收数据。git

 

WebSocket原理

WebSocket的协议颇为简单,在第一次handshake经过之后,链接便创建成功,其后的通信数据都是以”\x00″开头,以”\xFF”结尾。在客户端,这个是透明的,WebSocket组件会自动将原始数据“掐头去尾”。程序员

浏览器发出WebSocket链接请求,而后服务器发出回应,而后链接创建成功,这个过程一般称为“握手” (handshaking)。请看下面的请求和反馈信息:golang

 

 图1 WebSocket的request和response信息web

在请求中的"Sec-WebSocket-Key"是随机的,对于成天跟编码打交道的程序员,一眼就能够看出来:这个是一个通过base64编码后的数据。服务器端接收到这个请求以后须要把这个字符串链接上一个固定的字符串:算法

258EAFA5-E914-47DA-95CA-C5AB0DC85B11

即:f7cb4ezEAl6C3wRaU6JORA==链接上那一串固定字符串,生成一个这样的字符串:浏览器

f7cb4ezEAl6C3wRaU6JORA==258EAFA5-E914-47DA-95CA-C5AB0DC85B11

对该字符串先用 sha1安全散列算法计算出二进制的值,而后用base64对其进行编码,便可以获得握手后的字符串:安全

rE91AJhfC+6JdVcVXOGJEADEJdQ=

将之做为响应头Sec-WebSocket-Accept的值反馈给客户端。

 

Go实现WebSocket

Go语言标准包里面没有提供对WebSocket的支持,可是在由官方维护的go.net子包中有对这个的支持,你能够经过以下的命令获取该包:

go get golang.org/x/net/websocket

WebSocket分为客户端和服务端,接下来咱们将实现一个简单的例子:用户输入信息,客户端经过WebSocket将信息发送给服务器端,服务器端收到信息以后主动Push信息到客户端,而后客户端将输出其收到的信息,客户端的代码以下:

<html>
<head></head>
<body>
    <script type="text/javascript">
        var sock = null;
        var wsuri = "ws://127.0.0.1:1234";

        window.onload = function() {

            console.log("onload");

            sock = new WebSocket(wsuri);

            sock.onopen = function() {
                console.log("connected to " + wsuri);
            }

            sock.onclose = function(e) {
                console.log("connection closed (" + e.code + ")");
            }

            sock.onmessage = function(e) {
                console.log("message received: " + e.data);
            }
        };

        function send() {
            var msg = document.getElementById('message').value;
            sock.send(msg);
        };
    </script>
    <h1>WebSocket Echo Test</h1>
    <form>
        <p>
            Message: <input id="message" type="text" value="Hello, world!">
        </p>
    </form>
    <button onclick="send();">Send Message</button>
</body>
</html>

能够看到客户端JS,很容易的就经过WebSocket函数创建了一个与服务器的链接sock,当握手成功后,会触发WebScoket对象的onopen事件,告诉客户端链接已经成功创建。客户端一共绑定了四个事件。

  • 1)onopen 创建链接后触发
  • 2)onmessage 收到消息后触发
  • 3)onerror 发生错误时触发
  • 4)onclose 关闭链接时触发

咱们服务器端的实现以下:

 1 package main
 2 
 3 import (
 4     "golang.org/x/net/websocket"
 5     "fmt"
 6     "log"
 7     "net/http"
 8 )
 9 
10 func Echo(ws *websocket.Conn) {
11     var err error
12 
13     for {
14         var reply string
15 
16         if err = websocket.Message.Receive(ws, &reply); err != nil {
17             fmt.Println("Can't receive")
18             break
19         }
20 
21         fmt.Println("Received back from client: " + reply)
22 
23         msg := "Received:  " + reply
24         fmt.Println("Sending to client: " + msg)
25 
26         if err = websocket.Message.Send(ws, msg); err != nil {
27             fmt.Println("Can't send")
28             break
29         }
30     }
31 }
32 
33 func main() {
34     http.Handle("/", websocket.Handler(Echo))
35 
36     if err := http.ListenAndServe(":1234", nil); err != nil {
37         log.Fatal("ListenAndServe:", err)
38     }
39 }
View Code

当客户端将用户输入的信息Send以后,服务器端经过Receive接收到了相应信息,而后经过Send发送了应答信息。

 

 

图2 WebSocket服务器端接收到的信息

经过上面的例子咱们看到客户端和服务器端实现WebSocket很是的方便,Go的源码net分支中已经实现了这个的协议,咱们能够直接拿来用,目前随着HTML5的发展,我想将来WebSocket会是Web开发的一个重点,咱们须要储备这方面的知识。

 

转载于https://astaxie.gitbooks.io/build-web-application-with-golang/zh/08.2.html

相关文章
相关标签/搜索