WebSocket入门

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上)。一个带有特定报头的HTTP握手被发送到了服务器端,接着在服务器端或是客户端就可以通过JavaScript来使用某种套接口(socket),这一套接口可被用来通过事件句柄异步地接收数据。

 

WebSocket原理

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

浏览器发出WebSocket连接请求,然后服务器发出回应,然后连接建立成功,这个过程通常称为“握手” (handshaking)。请看下面的请求和反馈信息:

 

 图1 WebSocket的request和response信息

在请求中的"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 οnclick="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

转载于:https://www.cnblogs.com/Paul-watermelon/p/11580563.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/391185.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ml dl el学习_DeepChem —在生命科学和化学信息学中使用ML和DL的框架

ml dl el学习Application of Machine Learning and Deep Learning for Drug Discovery, Genomics, Microsocopy and Quantum Chemistry can create radical impact and holds the potential to significantly accelerate the process of medical research and vaccine developm…

2017-2018-1 20179215《Linux内核原理与分析》第二周作业

20179215《Linux内核原理与分析》第二周作业 这一周主要了解了计算机是如何工作的&#xff0c;包括现在存储程序计算机的工作模型、X86汇编指令包括几种内存地址的寻址方式和push、pop、call、re等几个重要的汇编指令。主要分为两部分进行这周的学习总结。第一部分对学习内容进…

Gradle复制文件/目录方法

2019独角兽企业重金招聘Python工程师标准>>> gradle复制文件/文件夹方法 复制文件 //复制IDE生成的classes.jar文件到build/libs中&#xff0c;并改名为FileUtils.jar. task copyFile(type:Copy) {delete build/libs/FileUtils.jarfrom(build/intermediates/bundles…

用户参与度与活跃度的区别_用户参与度突然下降

用户参与度与活跃度的区别disclaimer: I don’t work for Yammer, this is a public data case study, I’ve written it in a narrative format to make this case study more engaging to read.免责声明&#xff1a;我不为Yammer工作&#xff0c;这是一个公共数据案例研究&am…

重学TCP协议(6) 四次挥手

1. 四次挥手 客户端进程发出连接释放报文&#xff0c;并且停止发送数据。释放数据报文首部&#xff0c;FIN1&#xff0c;其序列号为sequ&#xff08;等于前面已经传送过来的数据的最后一个字节的序号加1&#xff09;&#xff0c;此时&#xff0c;客户端进入FIN-WAIT-1&#xff…

UML建模图实战笔记

一、前言 UML&#xff1a;Unified Modeling Language&#xff08;统一建模语言&#xff09;&#xff0c;使用UML进行建模的作用有哪些&#xff1a; 可以更好的理解问题可以及早的发现错误或者被遗漏的点可以更加方便的进行组员之间的沟通支持面向对象软件开发建模&#xff0c;可…

数据草拟:使您的团队热爱数据的研讨会

Learn the rules to Data Draw Up; a fun way to get your teams invested in data.了解数据收集的规则&#xff1b; 一种让您的团队投入数据的有趣方式。 Let’s keep things short. Metrics are one of the most important things in Product Management. They help us to u…

深入理解InnoDB(5)-文件系统

1. 数据库和文件系统的关系 像 InnoDB 、 MyISAM 这样的存储引擎都是把表存储在文件系统上的。当我们想读取数据的时候&#xff0c;这些存储引擎会从文件系统中把数据读出来返回给我们&#xff0c;当我们想写入数据的时候&#xff0c;这些存储引擎会把这些数据又写回文件系统。…

Digital River拉来Netconcepts站台 亚太营销服务升级

它是大洋彼岸的一家网络软件下载、分销商&#xff0c;很多重量级的软件行业领军企业都是其客户&#xff0c;它一直低调摸索亚太营销的路子&#xff0c;在今年九月份&#xff0c;它一改常态&#xff0c;高调宣布入华&#xff0c;三个月后&#xff0c;它带来了最新消息&#xff1…

按下按钮_按下

按下按钮Updated with the latest data: 23/8/2020更新最新数据&#xff1a;23/8/2020 As restrictions are lifted for Laois and Offaly, difficult times are set to continue for the people of Kildare, at least for another couple of weeks, as they continue to fight…

windows中怎么添加定时任务

linux中有crontab定时任务&#xff0c;很方便 其实windows也有类似的 需求&#xff1a;定时执行python脚本 1、Windows键R&#xff0c;调出此窗口&#xff0c;输入compmgmt.msc 2、 转载于:https://www.cnblogs.com/gcgc/p/11594467.html

重学TCP协议(7) Timestamps 选项

1.Timestamps 选项的组成部分 时间戳选项占10个字节 kind(1字节) &#xff0b; length(1字节) info (8字节)&#xff0c;其中kind8&#xff0c;length10&#xff0c;info由timestamp&#xff08;TS value&#xff09;和timestamp echo&#xff08;TS Echo Reply&#xff09;两…

c++ 时间序列工具包_我的时间序列工具包

c 时间序列工具包When it comes to time series forecasting, I’m a great believer that the simpler the model, the better.关于时间序列预测&#xff0c;我坚信模型越简单越好。 However, not all time series are created equal. Some time series have a strongly defi…

bash 的相关配置

bash 参数自动补全 请安装 bash-completion bash 提示符 说明&#xff1a;参考文档 1. 简洁风格 if [[ ${EUID} 0 ]] ; then PS1\[\033[01;32m\][\[\033[01;35m\]\u\[\033[01;37m\] \w\[\033[01;32m\]]\$\[\033[00m\] else PS1\[\033[01;32m\][\u\[\033[01;37m\] \w\[\033[01;…

LINUX系统安装和管理

目录 一.应用程序 对比应用程序与系统命令的关系 典型应用程序的目录结构 常见的软件包装类型 二.RPM软件包管理 1.RPM是什么&#xff1f; 2.RPM命令的格式 查看已安装的软件包格式 查看未安装的软件包 3.RPM安装包从哪里来&#xff1f; 4.挂载的定义 挂载命令moun…

adobe 书签怎么设置_让我们设置一些规则…没有Adobe Analytics处理规则

adobe 书签怎么设置Originally published at Analyst Admin.最初发布于Analyst Admin 。 In my experience working with Adobe Analytics, I’ve found that Processing Rules help in some cases, but oftentimes they create more work. I try to avoid using Processing R…

详解linux下安装python3环境

1、下载python3.5源码包首先去python官网下载python3的源码包&#xff0c;网址&#xff1a;https://www.python.org/ 进去之后点击导航栏的Downloads&#xff0c;也可以鼠标放到Downloads上弹出菜单选择Source code&#xff0c;表示源码包&#xff0c;这里选择最新版本3.5.2&am…

重学TCP协议(8) TCP的11种状态

TCP的11种状态 为了逻辑更加清晰&#xff0c;假设主动打开连接和关闭连接皆为客户端&#xff0c;被动打开连接和关闭连接皆为服务端 客户端独有的&#xff1a;&#xff08;1&#xff09;SYN_SENT &#xff08;2&#xff09;FIN_WAIT1 &#xff08;3&#xff09;FIN_WAIT2 &…

肯尼亚第三方支付_肯尼亚的COVID-19病例正在Swift增加,我们不知道为什么。

肯尼亚第三方支付COVID-19 cases in Kenya are accelerating rapidly. New cases have increased 300% month-over-month since April of this year while global and regional media have reported on the economic toll of stringent lock-down measures and heavy-handed go…

Java 集合 List Arrays.asList

2019独角兽企业重金招聘Python工程师标准>>> 参考链接&#xff1a;阿里巴巴Java开发手册终极版v1.3.0 【强制】使用工具类 Arrays.asList()把数组转换成集合时&#xff0c;不能使用其修改集合相关的方 法&#xff0c;它的 add/remove/clear 方法会抛出 UnsupportedO…