用 Go 编写一个简单的 WebSocket 推送服务
用 Go 编写一个简单的 WebSocket 推送服务
本文中代码可以在 github.com/alfred-zhong/wserver 获取。
背景
最近拿到需求要在网页上展示报警信息。以往报警信息都是通过短信,微信和 App 推送给用户的,现在要让登录用户在网页端也能实时接收到报警推送。
依稀记得以前工作的时候遇到过类似的需求。因为以前的浏览器标准比较陈旧,并且那时用 Java 较多,所以那时候解决这个问题就用了 Comet4J。具体的原理就是长轮询,长链接。但现在毕竟 html5 流行开来了,IE 都被 Edge 接替了,再用以前这种技术就显得过时。
很早以前就听过 WebSocket 的大名,但因为那时很多用户的浏览器还不支持,所以对这个技术也就是浅尝辄止,没有太深入研究过。现在趁着项目需要,就来稍微深入了解一下。
websocket 简介
以往浏览器要获取服务端数据,都是通过发送 HTTP 请求,然后等待服务端回应的。也就是说浏览器端一直是整个请求的发起者,只有它主动,才能获取到数据。而要让浏览器一侧能够获取到服务端的实时数据,就需要不停地向服务端发起请求。虽然大多数情况下并没有获取到实际数据,但这大大增加了网络压力,对于服务端来说压力也直线上升。

后来我们学会了使用长连接 + 长轮询的方式。换句话说,也就是延长 HTTP 请求的存在时间,尽量保持 HTTP 连接。虽然这在一定程度上降低了不少压力,但仍然需要不停地进行轮询,也做不到真正的实时性。(借用一张图)

随着 HTML5 的到来,WebSocket 在 2011 年被定为标准(详情请参见 RFC 6455)。
借用 《Go Web 编程》的话。WebSocket 采用了一些特殊的报头,使得浏览器和服务器只需要做一个握手的动作,就可以在浏览器和服务器之间建立一条连接通道。且此连接会保持在活动状态,你可以使用 JavaScript 来向连接写入或从中接收数据,就像在使用一个常规的 TCP Socket 一样。它解决了 Web 实时化的问题。
由于 WebSocket 是全双工通信,所以当建立了 WebSocket 连接之后,接下来的通信就类似于传统的 TCP 通信了。客户端和服务端可以相互发送数据,不再有实时性的问题。

开发包的选择
在 Go 官方的 SDK 中,并不包含对 WebSocket 的支持,所以必须使用第三方库。
要使用 Golang 开发 WebSocket,选择基本就在 x/net/websocket 和 gorilla/websocket 之间。《Go Web 编程》一书中的例子使用了 x/net/websocket 作为开发包,而且貌似它也更加官方且正式。而实际根据我在网上查询得到的反馈看来,并非如此。x/net/websocket 貌似 Bug 较多,且较为不稳定,问题解决也并不及时。相比之下,gorilla/websocket 则更加优秀。
还有对于 Gorilla web toolkit 组织的贡献,必须予以感谢。
用 Go 编写一个简单的 WebSocket 推送服务的更多相关文章
- SSM项目使用GoEasy 实现web消息推送服务
一.背景 之前项目需要做一个推送功能,最开始我用websocket实现我的功能.使用websocket的好处是免费自主开发,但是有几个问题:1)浏览器的兼容问题,尤其是低版本的ie:2)因为是推送 ...
- 移动互联网实战--Apple的APNS桩推送服务的实现(2)
前记: 相信大家在搞IOS推送服务的开发时, 会直接使用javapns api来简单实现, 调试也直连Apple的APNS服务(产品/测试版)来实现. 很少有人会写个APNS的桩服务, 事实也是如此. ...
- springboot搭建一个简单的websocket的实时推送应用
说一下实用springboot搭建一个简单的websocket 的实时推送应用 websocket是什么 WebSocket是一种在单个TCP连接上进行全双工通信的协议 我们以前用的http协议只能单 ...
- 编写一个简单的C++程序
编写一个简单的C++程序 每个C++程序都包含一个或多个函数(function),其中一个必须命名为main.操作系统通过调用main来运行C++程序.下面是一个非常简单的main函数,它什么也不干, ...
- 使用Java编写一个简单的Web的监控系统cpu利用率,cpu温度,总内存大小
原文:http://www.jb51.net/article/75002.htm 这篇文章主要介绍了使用Java编写一个简单的Web的监控系统的例子,并且将重要信息转为XML通过网页前端显示,非常之实 ...
- 编写一个简单的Web Server
编写一个简单的Web Server其实是轻而易举的.如果我们只是想托管一些HTML页面,我们可以这么实现: 在VS2013中创建一个C# 控制台程序 编写一个字符串扩展方法类,主要用于在URL中截取文 ...
- javascript编写一个简单的编译器(理解抽象语法树AST)
javascript编写一个简单的编译器(理解抽象语法树AST) 编译器 是一种接收一段代码,然后把它转成一些其他一种机制.我们现在来做一个在一张纸上画出一条线,那么我们画出一条线需要定义的条件如下: ...
- Java入门篇(一)——如何编写一个简单的Java程序
最近准备花费很长一段时间写一些关于Java的从入门到进阶再到项目开发的教程,希望对初学Java的朋友们有所帮助,更快的融入Java的学习之中. 主要内容包括JavaSE.JavaEE的基础知识以及如何 ...
- 用C语言编写一个简单的词法分析程序
问题描述: 用C或C++语言编写一个简单的词法分析程序,扫描C语言小子集的源程序,根据给定的词法规则,识别单词,填写相应的表.如果产生词法错误,则显示错误信息.位置,并试图从错误中恢复.简单的恢复方法 ...
随机推荐
- WDF驱动的编译、调试、安装
编译和调试使用WDK编译,源代码应包括wdf.h,ntddk.h以及KMDF_VERSION=1,编译使用/GS.KMDF包括以下库:1). WdfDriverEntry.lib(编译时绑定):驱动入 ...
- 芝麻HTTP:Python爬虫入门之URLError异常处理
1.URLError 首先解释下URLError可能产生的原因: 网络无连接,即本机无法上网 连接不到特定的服务器 服务器不存在 在代码中,我们需要用try-except语句来包围并捕获相应的异常.下 ...
- pat1061-1070
1061 我想吐槽这题的题意不够清楚,不过下次得长记性,对于模糊的题意要大胆猜测,而不是固执己见 #include<iostream> #include<cstdio> #in ...
- Acperience HDU - 5734
Deep neural networks (DNN) have shown significant improvements in several application domains includ ...
- iOS - Swift Enumerations or how to annoy Tom
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- Web 小案例 -- 网上书城(三)
内容有点乱,有兴趣的同伙可依照后面的案例结构结合文章进行阅读 和网上购买东西一样,你可以在不登录的状态下去浏览商品,但是当你想把自己中意的东西加入购物车或是收藏起来就需要你拥有自己的账号然后登录后才可 ...
- Python Cookbook(第3版)中文版:15.17 传递文件名给C扩展
15.17 传递文件名给C扩展¶ 问题¶ 你需要向C库函数传递文件名,但是需要确保文件名根据系统期望的文件名编码方式编码过. 解决方案¶ 写一个接受一个文件名为参数的扩展函数,如下这样: static ...
- CF908G Original Order
题目大意: 定义\(R(x) = 每个数在各数位排序后得到的数\) 例如:\(R(321597) = 123579\) 给定一个\(n<=10^{700}\),求\(\sum _{i=1}^n ...
- [Baltic2004]数字序列
原题请见<左偏树的特点及其应用>BY 广东省中山市第一中学 黄源河 题意 给出序列\(a[1...n]\),要求构造序列\(b[1...n]\)使得\(\sum_{i=1}^{n}|a_i ...
- BZOJ4321: queue2
题面 传送门 Sol 先设一个套路的状态:\(f[i][j]\)表示到第\(i\)个人,有\(j\)对冲突 但是我们不能确定\(i-1\),所以不好决策i的位置 所以再加一维\(0/1\),\(f[0 ...