当前位置:网站首页>On using go language to create websocket service
On using go language to create websocket service
2022-04-23 12:06:00 【ysds20211402】
from : Micro reading https://www.weidianyuedu.com
How to use it today Go Language establish WebSocket service , The first two parts of the article briefly introduce WebSocket Agreement and use Go How to create a standard library WebSocket service . The third part is the practice link we used gorilla/websocket Libraries help us build quickly WebSocket service , It helps to encapsulate the use of Go Standard library implementation WebSocket Basic logic of service , Let's get rid of the tedious underlying code , Build quickly according to business requirements WebSocket service .
WebSocket Introduce
WebSocket Communication protocol through a single TCP Connection provides full duplex communication channel . And HTTP comparison ,WebSocket You don't need to send a request to get a response . It allows two-way data flow , So you just need to wait for messages from the server . When Websocket When available , It will send you a message . For services requiring continuous data exchange ( For example, instant messaging program , Online games and real-time trading system ),WebSocket Is a good solution . WebSocket Connection requested by browser , And the server responds , Then establish a connection , This process is often referred to as handshaking . WebSocket The special header in requires only one handshake between the browser and the server to establish a connection , The connection will remain active throughout its lifecycle . WebSocket Solved many real-time problems Web Development challenges , And with the traditional HTTP comparison , It has many advantages :
Lightweight header reduces data transmission overhead .
Single Web Client only needs one TCP Connect .
WebSocket The server can push data to Web client .
WebSocket Protocol implementation is relatively simple . It USES HTTP Protocol initial handshake . Establish the connection after the handshake is successful ,WebSocket Essentially using the original TCP Read / Write data .
Client requests are as follows :
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
This is the server response :
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
How to be in Go Created in WebSocket application
Based on Go Language built in net/http Library writing WebSocket The server , You need :
Shake hands
Receive data frame from client
Send data frame to client
Close handshake
Shake hands
First , Let's create a WebSocket End point's HTTP The handler :
// HTTP server with WebSocket endpoint
func Server() {undefined
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {undefined
ws, err := NewHandler(w, r)
if err != nil {undefined
// handle error
}
if err = ws.Handshake(); err != nil {undefined
// handle error
}
…
Then initialize WebSocket structure .
The initial handshake request always comes from the client . The server has determined WebSocket After the request , A handshake response is required to respond .
please remember , You can't use http.ResponseWriter Write response , Because once you start sending responses , It will close the TCP Connect ( This is a HTTP Determined by the operation mechanism of the agreement , Close connection after sending response ).
therefore , You need to use HTTP hijacked (hijack). By hijacking , Can take over the foundation TCP Connection handlers and bufio.Writer. This enables the TCP Read and write data when connected .
// NewHandler initializes a new handler
func NewHandler(w http.ResponseWriter, req *http.Request) (*WS, error) {undefined
hj, ok := w.(http.Hijacker)
if !ok {undefined
// handle error
} .....
}
To complete the handshake , The server must respond with the appropriate headers .
// Handshake creates a handshake header
func (ws *WS) Handshake() error {undefined
hash := func(key string) string {undefined
h := sha1.New()
h.Write([]byte(key))
h.Write([]byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}(ws.header.Get("Sec-WebSocket-Key"))
.....
}
Client initiated WebSocket For connection requests Sec-WebSocket-key It's randomly generated , And is Base64 Coded . After accepting the request , The server needs to attach this key to a fixed string . Suppose the secret key is x3JJHMbDL1EzLkh9GBhXDw==. In this case , have access to SHA-1 Calculate binary value , And use Base64 Code it . obtain HSmrc0sMlYUkAGmm5OPpG2HaGWk=. Then use it as Sec-WebSocket-Accept Value of response header .
Transmit data frame
After successful handshake , Your application can read data from or write data to clients .WebSocket The specification defines a specific frame format to be used between a client and a server . This is the bit pattern of the framework :
chart : Bit mode of data frame transmission
Use the following code to decode the client payload :
// Recv receives data and returns a Frame
func (ws *WS) Recv() (frame Frame, _ error) {undefined
frame = Frame{}
head, err := ws.read(2)
if err != nil {undefined
// handle error
}
In turn, , These lines allow data to be encoded :
// Send sends a Frame
func (ws *WS) Send(fr Frame) error {undefined
// make a slice of bytes of length 2
data := make([]byte, 2)
// Save fragmentation & opcode information in the first byte
data[0] = 0x80 | fr.Opcode
if fr.IsFragment {undefined
data[0] &= 0x7F
}
.....
Close handshake
When one of the parties sends a closed frame with the status of closed as the payload , Handshake will close . Optional , The party sending the shutdown frame can send the shutdown reason in the payload . If the shutdown is initiated by the client , Then the server should send the corresponding shutdown frame in response .
// Close sends a close frame and closes the TCP connection
func (ws *Ws) Close() error {undefined
f := Frame{}
f.Opcode = 8
f.Length = 2
f.Payload = make([]byte, 2)
binary.BigEndian.PutUint16(f.Payload, ws.status)
if err := ws.Send(f); err != nil {undefined
return err
}
return ws.conn.Close()
}
Use third-party library to build quickly WebSocket service
As can be seen from the above chapters Go Self contained net/http Library implementation WebSocket Service is still too complicated . Fortunately, there are many right WebSocket Support a good third-party library , Can reduce a lot of our underlying coding work . Here we use gorilla web toolkit Another library of the family gorilla/websocket To achieve our WebSocket service , Build a simple one Echo service (echo It means echo , What does the client send , The server sends the message back to the client ).
We are http_demo Project handler Create a new one in the directory ws Subdirectories are used to store WebSocket Request handler for service related routing .
Add two routes :
/ws/echo echo Applied WebSocket Routing of services .
/ws/echo_display echo Routing of the client page of the application .
establish WebSocket Server side
// handler/ws/echo.go
package ws
import (
"fmt"
"github.com/gorilla/websocket"
"net/http"
)
var upgrader = websocket.Upgrader{undefined
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
func EchoMessage(w http.ResponseWriter, r *http.Request) {undefined
conn, _ := upgrader.Upgrade(w, r, nil) // Remember to do error handling in practical application
for {undefined
// Read messages from clients
msgType, msg, err := conn.ReadMessage()
if err != nil {undefined
return
}
// Print messages to standard output
fmt.Printf("%s sent: %s\n", conn.RemoteAddr(), string(msg))
// Write messages back to the client , Complete echo
if err = conn.WriteMessage(msgType, msg); err != nil {undefined
return
}
}
}
conn The type of variable is *websocket.Conn, websocket.Conn Type is used to represent WebSocket Connect . Server application from HTTP Request handler call Upgrader.Upgrade Method to get *websocket.Conn
Call connected WriteMessage and ReadMessage Method to send and receive messages . above msg After receiving it, it is sent back to the client below .msg The type is []byte.
establish WebSocket client
The request handler corresponding to the front-end page routing is as follows , Go straight back to views/websockets.html Just render the page to the browser .
// handler/ws/echo_display.go
package ws
import "net/http"
func DisplayEcho(w http.ResponseWriter, r *http.Request) {undefined
http.ServeFile(w, r, "views/websockets.html")
}
websocket.html We need to use JavaScript Connect WebScoket Service sends and receives messages , The reason is that I only post JS Code. , Complete code can get the download link through the official account of this section. .
<form>
<input id="input" type="text" />
<button οnclick="send()">Send</button>
<pre id="output"></pre>
</form>
...
<script>
var input = document.getElementById("input");
var output = document.getElementById("output");
var socket = new WebSocket("ws://localhost:8000/ws/echo");
socket.onopen = function () {undefined
output.innerHTML += "Status: Connected\n";
};
socket.onmessage = function (e) {undefined
output.innerHTML += "Server: " + e.data + "\n";
};
function send() {undefined
socket.send(input.value);
input.value = "";
}
</script>
...
Registered routing
After the server and client programs are ready , We register the route and the corresponding request handler for them according to the agreed path :
// router/router.go
func RegisterRoutes(r *mux.Router) {undefined
...
wsRouter := r.PathPrefix("/ws").Subrouter()
wsRouter.HandleFunc("/echo", ws.EchoMessage)
wsRouter.HandleFunc("/echo_display", ws.DisplayEcho)
}
Test verification
Access after service restart http://localhost:8000/ws/echo_display, Any message entered in the input box can be echoed back to the browser .
picture
The server prints the received message to the terminal and then calls the writeMessage Send the message back to the client , Records can be viewed in the terminal .
summary
WebSocket It is widely used in the frequently updated applications , Conduct WebSocket Programming is also a necessary skill we need to master . The practice of the article is a little simpler , No error or security checks . Mainly to clarify the general process . About gorilla/websocket For more details, you need to check the official documents when using .
版权声明
本文为[ysds20211402]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231203047375.html
边栏推荐
- Golang Pen & interview 01
- Nativeformysql connects to MySQL 8 prompt: 1251 - client does not support authentication protocol
- 《通用数据保护条例》(GDPR)系列解读三:欧洲子公司如何向国内母公司回传数据?
- Fastjson 2 is coming, the performance continues to improve, and it can fight for another ten years
- Here comes the detailed picture and text installation tutorial of H5 game
- 魔域来了H5游戏详细图文架设教程
- How do programmers finalize nucleic acid statistics with 130 lines of code
- ImportError: libX11. so. 6: cannot open shared object file: No such file or directory
- Worder font page font comparison table
- 关于使用Go语言创建WebSocket服务浅谈
猜你喜欢

Fastjson 2 is coming, the performance continues to improve, and it can fight for another ten years

如果你是一个Golang面试官,你会问哪些问题?

Yunna | fixed assets inventory supports multiple inventory methods (asset inventory)

同态加密技术学习

IDEA 数据库插件Database Navigator 插件

Application of remote integrated monitoring system in power distribution room in 10kV prefabricated cabin project

How to expand the capacity of the server in the 100 million level traffic architecture? Well written!

Sofa weekly | excellent Committee of the year, contributor of this week, QA of this week

C# F23. Stringsimilarity Library: String repeatability, text similarity, anti plagiarism

智能多线弹性云增加独立的IP地址,如何实现多线功能?
随机推荐
The listing of saiweidian Technology Innovation Board broke: a decrease of 26% and the market value of the company was 4.4 billion
Nacos Foundation (7): Configuration Management
1.Electron开发环境搭建
AcWing 1874. Moo encryption (enumeration, hash)
Tips for installing MySQL service in windows11: Install / Remove of the Service denied
Nacos Foundation (8): login management
【Redis 系列】redis 学习十三,Redis 常问简单面试题
IMEU如何与IMCU相关联(IM 5.5)
Optimize connections using connection groups (IM 6)
如果你是一个Golang面试官,你会问哪些问题?
面了一圈,整理了这套面试题。。
5-minute NLP: text to text transfer transformer (T5) unified text to text task model
激活函数之阶跃函数
Idea database navigator plug-in
Golang Pen & interview 01
2022 love analysis · panoramic report of industrial Internet manufacturers
获取钉钉考勤机打卡记录
程序员如何用130行代码敲定核酸统计
Nacos Foundation (9): Nacos configuration management from single architecture to microservices
Idea code quality specification plug-in sonarlint