Go语言实现的WebSocket

Posted Golang语言社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言实现的WebSocket相关的知识,希望对你有一定的参考价值。

  • 最终的效果如下


    Go语言实现的WebSocket

    Web端上传的信息


    Go语言实现的WebSocket

    Web端得到的打印的信息


Go语言实现的WebSocket

服务端的代码的实现


Go语言实现的WebSocket

服务端的信息


  • WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。WebSocket是html5的重要特性,它实现了基于浏览器的远程socket,它使浏览器和服务器可以进行全双工通信,许多浏览器Firefox、Google Chrome和Safari都已对此做了支持

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

  • 很多的游戏的服务都是采用的是Socket,因为HTTP协议相对而言比较耗费性能, 随着HTML5的发展,WebSocket也逐渐发展成为很多页游公司接下来开发的一些手段。

  • 安卓推送的原理: C2DM 推送 (Google) C2DM 推送简介 : 全称 Cloudto Device Messaging, Google 提供的 推送解决方案;

    • 运行方式 : 提供一个轻量级机制, 允许服务器通知应用程序, 主动与客户端进行数据交互, 处理消息排队, 并向运行于目标设备的应用程序分发消息;

    • 优点 : Google 提供的原生框架, 无需在应用中添加第三方代码 和 部署服务器端;

    • 缺点 : 1.该推送依赖 Google 服务器, 需要绑定 Google 帐号, 目前在中国 Google 被屏蔽, 无法使用; 2. 许多手机厂商去掉了软件中的该模块;

  • android 平台上长连接的实现

    • Timer
      Android 的 Timer 类可以用来计划需要循环执行的任务,Timer 的问题是它需要用 WakeLock 让 CPU 保持唤醒状态,这样会大量消耗手机电量,大大减短手机待机时间。

    • AlarmManager 这篇文章有介绍怎么使用AlarmManager安卓网络和电量优化
      AlarmManager 是 Android 系统封装的用于管理 RTC 的模块,RTC (Real Time Clock) 是一个独立的硬件时钟,可以在 CPU 休眠时正常运行,在预设的时间到达时,通过中断唤醒 CPU。
      这意味着,如果我们用 AlarmManager 来定时执行任务,CPU 可以正常的休眠,只有在需要运行任务时醒来一段很短的时间。极光推送的 Android SDK 就是基于这种技术实现的。
      极光官方文档

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


WebSocket 原理


  • WebSocket的协议:在第一次handshake通过以后,连接便建立成功,其后的通讯数据都是以”x00″开头,以”xFF”结尾。在客户端,这个是透明的,WebSocket组件会自动将原始数据“掐头去尾”。


Go语言实现的WebSocket

request的信息.png


 1GET http://localhost:8080/shiming HTTP/1.1
2Host: localhost:8080
3Connection: Upgrade
4Pragma: no-cache
5Cache-Control: no-cache
6Upgrade: websocket
7Origin: file://
8Sec-WebSocket-Version: 13
9User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0
10Accept-Encoding: gzip, deflate, sdch, br
11Accept-Language: zh-CN,zh;q=0.8
12Cookie: _ga=GA1.1.27955907.1529919744
13Sec-WebSocket-Key: PCD+pA79juC6tlBK9zD3Vw==
14Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
  • Sec-WebSocket-Key这个是个随机的值,是一个经过base64编写后的数据Sec-WebSocket-Key: PCD+pA79juC6tlBK9zD3Vw==

  • 然后服务器收到这个请求之后把这个字符串连接上一个固定的字符串 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 为啥是这样的,我目前还不明白,仅仅是自己记录下而已。

  • 最终得到:

1PCD+pA79juC6tlBK9zD3Vw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
  • 对该字符使用shal 安全散列算法计算出二进制的值,然后用base64 对其进行编码,即可以得到握手的字符串: 8+5CLWTBYLARKoxBxS5uk6s6zZo= ,如下图所示


Go语言实现的WebSocket

response信息.png


1HTTP/1.1 101 Switching Protocols
2Upgrade: websocket
3Connection: Upgrade
4Sec-WebSocket-Accept: 8+5CLWTBYLARKoxBxS5uk6s6zZo=
  • Sec-WebSocket-Accept作为响应头的值反馈给客户端。


Go语言实现Websocket


  • 由于Go语言标准包里面没有对WebSocket的支持,但是官方维护的go.net对这个有支持,所以可以获取

1go get golang.org/net/websocket
  • 但是有个小问题,当我 go get后,我在代码中导入包会报错,同时去掉x也不行,所以我在本地目录创建了一个x的目录,然后把net全部放进去了

    Go语言实现的WebSocket

    注意问题.png


    Go语言实现的WebSocket

    导包

  • html 代码


 1<html>
2<head>
3    <title>好好学习</title>
4</head>
5<body>
6<script type="text/javascript">
7    var sock = null;
8    // var wsuri = "wss://127.0.0.1:8080"; //本地的地址 是可以改变的哦
9     var wsuri = "ws://localhost:8080/shiming"//本地的地址 是可以改变的哦
10
11
12    window.onload = function({
13        //可以看到客户端JS,很容易的就通过WebSocket函数建立了一个与服务器的连接sock,当握手成功后,会触发WebScoket对象的onopen事件,告诉客户端连接已经成功建立。客户端一共绑定了四个事件。
14        console.log("开始了 onload");
15
16        sock = new WebSocket(wsuri);
17        //建立连接后触发
18        sock.onopen = function({
19            console.log(" 建立连接后触发 connected to " + wsuri);
20        }
21        // 关闭连接时候触发
22        sock.onclose = function(e{
23            console.log("关闭连接时候触发 connection closed (" + e.code + ")");
24        }
25        // 收到消息后触发
26        sock.onmessage = function(e{
27            console.log("收到消息后触发 message received: " + e.data);
28        }
29        //发生错误的时候触发
30        sock.onerror=function (e{
31            console.log("发生错误时候触发"+wsuri)
32        }
33    };
34     //如果sock被关闭掉了 这里 也会报错的啊
35    function send({
36        var msg = document.getElementById('message').value;
37        sock.send(msg);
38    };
39</script>

40<h1>GoWebSocketDemo</h1>
41<form>
42    <p>
43        Message: <input id="message" type="text" value="你好啊  shiming 小哥哥  嘿嘿   ">
44    </p>
45</form>
46<button onclick="send();">给服务器发送消息</button>
47</body>
48</html>
  • go 代码

 1package main
2
3import (
4    "fmt"
5    "net/http"
6    //草拟吗 自己创建的目录 哈哈哈哈哈    还好我比较聪明  要不然 就完蛋了  麻痹
7    "golang.org/x/net/websocket"
8    "log"
9)
10
11func main() {
12    fmt.Println("Go语言标准包里面没有提供对WebSocket的支持,但是在由官方维护的go.net子包中有对这个的支持 go get golang.org/x/net/websocket")
13    //打印这个信息就,os.Exit(1)  退出程序
14    //log.Fatal("shiming")  todo  草拟吗 啊   看清楚啊   后面的域名的地址 有个老子的名字啊
15    http.Handle("/shiming",websocket.Handler(Echo))
16     if err:=http.ListenAndServe(":8080",nil);err!=nil{
17        log.Fatal(err)
18     }
19
20
21}
22
23func Echo(w *websocket.Conn)  {
24    var error error
25    for   {
26        var reply string
27        if  error= websocket.Message.Receive(w,&reply);error!=nil{
28            fmt.Println("不能够接受消息 error==",error)
29            break
30        }
31        fmt.Println("能够接受到消息了--- ",reply)
32        msg:="我已经收到消息 Received:"+reply
33        //  连接的话 只能是   string;类型的啊
34        fmt.Println("发给客户端的消息: "+msg)
35
36        if error = websocket.Message.Send(w, msg); error != nil {
37            fmt.Println("不能够发送消息 悲催哦")
38            break
39        }
40    }
41}
  • 说明一点:http.Handle("/shiming",websocket.Handler(funName)),如果在这里有路由的话,记得在  html中也要改成一样的, html中的代码 :var wsuri = "ws://localhost:8080/shiming"

  • x目录自己创建一个,把net包剪切进去就可以



版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。



Golang语言社区

ID:Golangweb

www.bytedancing.com

游戏服务器架构丨分布式技术丨大数据丨游戏算法学习


以上是关于Go语言实现的WebSocket的主要内容,如果未能解决你的问题,请参考以下文章

Go语言实现WebSocket协议

Go实现WebSocket案例

html5+go+websocket简单实例代码

使用 Go 语言创建 WebSocket 服务

go语言聊天室实现(二)gorilla/websocket中的聊天室示例

Go-websocket