Home > Article > Backend Development > How to implement multi-threaded Websocket communication using Go language
In recent years, real-time communication has become a basic need. WebSocket is a leader in real-time communication. It can realize real-time communication between the client and the server more quickly and effectively. The Go language has also been a popular language in recent years and is widely used in real-time communications. Taking advantage of the advantages of the Go language and the characteristics of multi-thread processing, the communication function of Websocket can be realized more efficiently and stably.
This article will focus on the Go language and introduce how to use it to implement multi-threaded Websocket communication, including some important function implementations, and will provide detailed code examples.
Before using Go language to implement Websocket communication, you need to understand some basic knowledge of Websocket communication. Websocket, like HTTP, is a network protocol based on TCP. But the difference is that it is not a request and response mode, but a continuous connection between the client and the server, allowing real-time communication between the two parties.
In the Go language, the first step to implement Websocket communication is to import the "net/http" and "github.com/gorilla/websocket" packages. Among them, "net/http" is used to create an HTTP server, and "github.com/gorilla/websocket" is a third-party package for Websocket. If this package is not available, you can use the "go get" command to install it.
import ( "fmt" "net/http" "github.com/gorilla/websocket" )
Use the "http.HandleFunc()" method in Go language to establish a Websocket connection, as shown below:
func main() { http.HandleFunc("/", handleConnections) http.ListenAndServe(":4000", nil) }
The above code uses " The http.HandleFunc()" method creates a handler function named "handleConnections", which is responsible for establishing Websocket connections. As you can see, the request path to establish a Websocket connection is "/", which is the root directory.
After establishing a Websocket connection, you need to configure some basic parameters for the connection request, such as protocol upgrade, read and write cache size, heartbeat timeout, etc.
var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { return true }, }
The above code is configured using "websocket.Upgrader", in which "ReadBufferSize" and "WriteBufferSize" specify the size of the read and write buffer area, and "CheckOrigin" is set to "true", indicating that all Source access request. If a specific source is required, it can be set according to specific requirements.
After the Websocket connection request is processed, the standard Websocket protocol handshake needs to be followed for protocol upgrade. In Go language, protocol upgrade can use Upgrader to perform protocol handshake and return connection handle (conn). The connection handle can be used to send and receive messages during the life cycle of Websocket connection.
func handleConnections(w http.ResponseWriter, r *http.Request) { // 通过Upgrader进行协议升级 ws, err := upgrader.Upgrade(w, r, nil) if err != nil { fmt.Println(err) } // 若协议升级成功,则跳转到另一个处理函数处理消息 go handleMessages(ws) }
In the handleConnections function, the protocol is first upgraded through Upgrader. If the upgrade is successful, call "go handleMessages(ws)" to start goroutine to start processing Websocket messages.
The next step is to process the Websocket message part. In the Go language, you can use an infinite loop to monitor the arrival of Websocket messages, and then process each message accordingly.
func handleMessages(ws *websocket.Conn) { for { messageType, p, err := ws.ReadMessage() if err != nil { fmt.Println(err) return } // 根据消息类型进行处理 switch messageType { case websocket.TextMessage: // 处理text类型消息 fmt.Println(string(p)) case websocket.BinaryMessage: // 处理binary类型消息 fmt.Println(p) } } }
In the handleMessages function, first use the "ws.ReadMessage()" method to read the Websocket message and process it according to the message type.
The last part is the sending part of Websocket message. In the Go language, you can use the Websocket connection handle "ws" to send data to the client.
func sendMessage(ws *websocket.Conn, messageType int, message []byte) error { if err := ws.WriteMessage(messageType, message); err != nil { return err } return nil }
In the sendMessage function, first send the message to the client through the "ws.WriteMessage()" method.
In order to improve the efficiency of Websocket communication, multi-threading needs to be used to process Websocket messages. In the Go language, you can use goroutine to implement concurrent processing.
In the Go language, starting a goroutine is very simple, just add "go" before the function.
go handleMessages(ws)
In actual development, Websocket usually needs to implement broadcast messages, that is, send a message to all connected clients. In the Go language, you can use a map to store all connected clients, then traverse and send messages to each client in turn.
var clients = make(map[*websocket.Conn]bool) // 所有连接的客户端 var broadcast = make(chan []byte) // 广播通道 func main() { http.HandleFunc("/", handleConnections) go handleMessages() http.ListenAndServe(":4000", nil) } func handleConnections(w http.ResponseWriter, r *http.Request) { // 通过Upgrader进行协议升级 ws, err := upgrader.Upgrade(w, r, nil) if err != nil { fmt.Println(err) } // 若协议升级成功,则将客户端存入map clients[ws] = true } func handleMessages() { for { // 从广播通道中获取消息 message := <- broadcast // 对所有连接的客户端发送消息 for client := range clients { if err := client.WriteMessage(websocket.TextMessage, message); err != nil { fmt.Println(err) delete(clients, client) return } } } }
In the above code, a broadcast channel (broadcast) is implemented for processing broadcast messages. At the same time, a map (clients) is created to store all connected clients. In the handleConnections function, when a new client connects, it will be stored in clients. In the handleMessages function, the broadcast channel gets new messages from it and sends them to all connected clients.
While processing Websocket messages in multiple threads, it is necessary to ensure data concurrency safety. In the Go language, you can use locks for concurrency security control. In the sample code of this article, "sync.RWMutex" is used to implement read-write locks to ensure concurrency safety.
var mutex = &sync.RWMutex{} func handleConnections(w http.ResponseWriter, r *http.Request) { // 通过Upgrader进行协议升级 ws, err := upgrader.Upgrade(w, r, nil) if err != nil { fmt.Println(err) } // 若协议升级成功,则将客户端存入map,并进行锁定 mutex.Lock() clients[ws] = true mutex.Unlock() } func handleMessages() { for { // 从广播通道中获取消息,并加锁 message := <- broadcast mutex.Lock() for client := range clients { if err := client.WriteMessage(websocket.TextMessage, message); err != nil { fmt.Println(err) client.Close() delete(clients, client) } } mutex.Unlock() } }
In the handleConnections function, after the connection is successful, the client is added to the map and locked. In the handleMessages function, lock before processing new messages to ensure data security.
In summary, using Go language to implement multi-threaded Websocket communication can improve the efficiency and stability of Websocket communication, and can easily implement broadcast messages. In practice, more complex functions can be implemented according to specific needs.
The above is the detailed content of How to implement multi-threaded Websocket communication using Go language. For more information, please follow other related articles on the PHP Chinese website!