# Go websocket 使用

WebSocket是HTML5的重要特性，它实现了基于浏览器的远程socket，它使浏览器和服务器可以进行全双工通信，许多浏览器（Firefox、Google Chrome和Safari）都已对此做了支持。

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

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

* 一个Web客户端只建立一个TCP连接
* Websocket服务端可以推送(push)数据到web客户端.
* 有更加轻量级的头，减少数据传送量

WebSocket URL的起始输入是ws\://或是wss\://（在SSL上）。下图展示了WebSocket的通信过程，一个带有特定报头的HTTP握手被发送到了服务器端，接着在服务器端或是客户端就可以通过JavaScript来使用某种套接口（socket），这一套接口可被用来通过事件句柄异步地接收数据。

![](https://224253890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MBRljtT_s45CDoES7pW%2Fsync%2Fb293c6536b7ac5b26a292969e6f5150e0d63cf55.png?generation=1593915731964104\&alt=media)

## 安装

```bash
go get golang.org/x/net/websocket
```

## Go websocket

服务端

```go
package main

import (
    "fmt"
    "golang.org/x/net/websocket"
    "net/http"
)

func echo(ws *websocket.Conn) {
    var err error
    for {
        var reply string
        if err = websocket.Message.Receive(ws, &reply); err != nil {
            fmt.Println("Can't receive")
            break
        }
        fmt.Println("Received back from client: " + reply)
        msg := "Received: " + reply
        fmt.Println("Sending to client: " + msg)
        if err = websocket.Message.Send(ws, msg); err != nil {
            fmt.Println("Can't send")
            break
        }
    }
}

func main() {
    http.Handle("/", websocket.Handler(echo))
    http.ListenAndServe(":8080", nil)
}
```

客户端

```markup
<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>
```

客户端一共绑定了四个事件。

* 1）onopen 建立连接后触发
* 2）onmessage 收到消息后触发
* 3）onerror 发生错误时触发
* 4）onclose 关闭连接时触发
