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.pswp.cn/news/391185.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391185.shtml
英文地址,請注明出處:http://en.pswp.cn/news/391185.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

安卓游戲開發推箱子_保持冷靜并砍箱子-開發

安卓游戲開發推箱子Hack The Box (HTB) is an online platform allowing you to test your penetration testing skills. It contains several challenges that are constantly updated. Some of them simulating real world scenarios and some of them leaning more towards …

自定義TabLayout

本文為kotlin仿開眼視頻Android客戶端的后續補充內容&#xff0c;本篇為大家介紹如何對TabLayout進行定制使用&#xff0c;基于項目需求&#xff0c;本篇主要對部分功能進行了定制&#xff0c;如&#xff1a;指示器距離文字的距離、文字選中加粗、文字選中變大等 本文部分代碼參…

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…

響應式網站設計_通過這個免費的四小時課程,掌握響應式網站設計

響應式網站設計This video tutorial from Kevin Powell teaches you to build responsive websites from scratch. 凱文鮑威爾(Kevin Powell)的這段視頻教程教您從頭開始構建響應式網站。 The course starts with explaining the core concepts needed to start thinking resp…

2017-2018-1 20179215《Linux內核原理與分析》第二周作業

20179215《Linux內核原理與分析》第二周作業 這一周主要了解了計算機是如何工作的&#xff0c;包括現在存儲程序計算機的工作模型、X86匯編指令包括幾種內存地址的尋址方式和push、pop、call、re等幾個重要的匯編指令。主要分為兩部分進行這周的學習總結。第一部分對學習內容進…

python:單例模式--使用__new__(cls)實現

單例模式&#xff1a;即一個類有且僅有一個實例。 那么通過python怎么實現一個類只能有一個實例呢。 class Earth:"""假如你是神&#xff0c;你可以創造地球"""print 歡迎來到地球# 生成一個地球 a Earth() print id(a)# 再生成一個地球 b Ear…

重學TCP協議(5) 自連接

1.自連接是什么 在發起連接時&#xff0c;TCP/IP的協議棧會先選擇source IP和source port&#xff0c;在沒有顯示調用bind()的情況下&#xff0c;source IP由路由表確定&#xff0c;source port由TCP/IP協議棧從local port range中選取尚未使用的port。 如果destination IP正…

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…

python:__new__()與__init__()

參考&#xff1a;https://blog.csdn.net/qq_41020281/article/details/79638370 轉載于:https://www.cnblogs.com/gcgc/p/11585599.html

重學TCP協議(6) 四次揮手

1. 四次揮手 客戶端進程發出連接釋放報文&#xff0c;并且停止發送數據。釋放數據報文首部&#xff0c;FIN1&#xff0c;其序列號為sequ&#xff08;等于前面已經傳送過來的數據的最后一個字節的序號加1&#xff09;&#xff0c;此時&#xff0c;客戶端進入FIN-WAIT-1&#xff…

mysql數據庫部分操作指令

用cmd開啟服務時拒絕訪問. 原因:不是管理員用戶&#xff0c;沒有權限 將服務中的 MySQL設置為手動啟動&#xff0c; 否則 開機自動啟動. 啟動mysql服務&#xff0c;用管理員權限打開dos界面 windowsX A 打開開始界面 點擊管理員開啟cmd 啟動服務&#xff1a;net start …

推箱子2-向右推!_保持冷靜并砍箱子-嗶

推箱子2-向右推!Hack The Box (HTB) is an online platform allowing you to test your penetration testing skills. It contains several challenges that are constantly updated. Some of them simulating real world scenarios and some of them leaning more towards a C…

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…

python:列表推導式

python中有種獨特的語法&#xff1a;推導式&#xff0c;可以將代碼壓縮到1行&#xff0c;但是不使用也不影響。 有三種&#xff1a;列表、字典、集合&#xff08;注意沒有元組推導式&#xff09; 列表推導式 # 1、一行代碼實現1—100之和(知識點&#xff1a;列表推導式) print(…

WPF中刪除打開過的圖片

WPF中刪除打開過的圖片 原文:WPF中刪除打開過的圖片在WPF中&#xff0c;當我們刪除打開過的圖片時&#xff0c;往往會遇到"...無法刪除&#xff0c;文件正在被另一個進程使用"的異常。即使當前文件是打開后關閉過的也不行。 這個問題的原因很簡單&#xff0c;是因為W…

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

1. 數據庫和文件系統的關系 像 InnoDB 、 MyISAM 這樣的存儲引擎都是把表存儲在文件系統上的。當我們想讀取數據的時候&#xff0c;這些存儲引擎會從文件系統中把數據讀出來返回給我們&#xff0c;當我們想寫入數據的時候&#xff0c;這些存儲引擎會把這些數據又寫回文件系統。…

vim捐贈_#PayItBackwards-一位freeCodeCamp畢業生如何向事業捐贈10,000美元

vim捐贈On Monday my phone suddenly started buzzing. Shawn Wang, AKA Swyx, had just tweeted about a donation hed made to freeCodeCamp.org.星期一&#xff0c;我的電話突然開始嗡嗡作響。 Awn Swyx的Shawn Wang剛剛在推特上發布了他對freeCodeCamp.org的捐款。 I glan…

Digital River拉來Netconcepts站臺 亞太營銷服務升級

它是大洋彼岸的一家網絡軟件下載、分銷商&#xff0c;很多重量級的軟件行業領軍企業都是其客戶&#xff0c;它一直低調摸索亞太營銷的路子&#xff0c;在今年九月份&#xff0c;它一改常態&#xff0c;高調宣布入華&#xff0c;三個月后&#xff0c;它帶來了最新消息&#xff1…