Server code
package main import ( "errors" "fmt" "net/http" "sync" "time" "/gorilla/websocket" ) // http upgrade websocket protocol configurationvar wsUpgrader = { // Allow all CORS cross-domain requests CheckOrigin: func(r *) bool { return true }, } // Client reads and writes messagestype wsMessage struct { messageType int data []byte } // Client connectiontype wsConnection struct { wsSocket * // The underlying websocket inChan chan *wsMessage // Read queue outChan chan *wsMessage // Write queue mutex // Avoid repeated shutdown of pipelines isClosed bool closeChan chan byte // Close notification} func (wsConn *wsConnection) wsReadLoop() { for { // Read a message msgType, data, err := () if err != nil { goto error } req := &wsMessage{ msgType, data, } // Put into the request queue select { case <- req: case <-: goto closed } } error: () closed: } func (wsConn *wsConnection) wsWriteLoop() { for { select { // Get a response case msg := <-: // Write to websocket if err := (, ); err != nil { goto error } case <-: goto closed } } error: () closed: } func (wsConn *wsConnection) procLoop() { // Start a gouroutine to send a heartbeat go func() { for { //Continuously writing data to the client, it is the same without it. The client can detect disconnection (2 * ) if err := (, []byte("heartbeat from server")); err != nil { ("heartbeat fail") () break } } }() // This is a synchronous processing model (just an example). If you want parallel processing, you can request one gorutine per request. Pay attention to controlling the number of concurrent goroutines!!! for { msg, err := () if err != nil { ("read fail") break } (string()) err = (, ) // After reading the data, write the data synchronously. It should be written asynchronously if err != nil { ("write fail") break } } } func wsHandler(resp , req *) { // The answering client informs the upgrade connection to websocket wsSocket, err := (resp, req, nil) if err != nil { return } wsConn := &wsConnection{ wsSocket: wsSocket, inChan: make(chan *wsMessage, 1000), outChan: make(chan *wsMessage, 1000), closeChan: make(chan byte), isClosed: false, } // Processor go () // Read coroutines go () // Write coroutines go () } func (wsConn *wsConnection) wsWrite(messageType int, data []byte) error { select { case <- &wsMessage{messageType, data}: case <-: return ("websocket closed") } return nil } func (wsConn *wsConnection) wsRead() (*wsMessage, error) { select { case msg := <-: return msg, nil case <-: } return nil, ("websocket closed") } func (wsConn *wsConnection) wsClose() { () () defer () if ! { = true close() } } func main() { ("/ws", wsHandler) ("0.0.0.0:7777", nil) }
Front-end code
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script> ("load", function(evt) { const output = ("output"); const input = ("input"); let ws; const print = function(message) { const d = ("div"); = message; (d); }; ("open").onclick = function(evt) { if (ws) { return false; } ws = new WebSocket("ws://localhost:7777/ws"); = function(evt) { print("OPEN"); } = function(evt) { print("CLOSE"); ws = null; } = function(evt) { print("RESPONSE: " + ); } = function(evt) { print("ERROR: " + ); } return false; }; ("send").onclick = function(evt) { if (!ws) { return false; } print("SEND: " + ); (); return false; }; ("close").onclick = function(evt) { if (!ws) { return false; } (); return false; }; }); </script> </head> <body> <table> <tr><td valign="top" width="50%"> <p>Click "Open" to create a connection to the server, "Send" to send a message to the server and "Close" to close the connection. You can change the message and send multiple times. </p> <form> <button >Open</button> <button >Close</button> <input type="text" value="Hello world!"> <button >Send</button> </form> </td><td valign="top" width="50%"> <div ></div> </td></tr></table> </body> </html>
This is the article about the demo sharing of websocket in Go. For more related websocket content, please search for my previous articles or continue browsing the following related articles. I hope everyone will support me in the future!