我正在用 Go 构建一个简单的聊天应用程序,并且希望在不使用任何外部库(例如 gorilla/websocket)的情况下实现 WebSocket 通信。我的目标是建立一个可以在两个用户之间发送和接收消息的 WebSocket 连接。
任何人都可以提供如何仅使用 Go 标准库设置 WebSocket 功能的基本示例吗?
使用外部库会减少手动工作,但根据您的要求,我设法制作了一些应该的东西,在这里 ->
package main
import (
"bufio"
"bytes"
"encoding/base64"
"fmt"
"net"
"net/http"
"strings"
"time"
)
func main() {
http.HandleFunc("/ws", wsHandler)
fmt.Println("Starting server on :8080")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println("Server error:", err)
}
}
func wsHandler(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Upgrade") != "websocket" {
http.Error(w, "Not a WebSocket request", http.StatusBadRequest)
return
}
conn, _, err := w.(http.Hijacker).Hijack()
if err != nil {
http.Error(w, "Failed to hijack connection", http.StatusInternalServerError)
return
}
defer conn.Close()
// WebSocket handshake
key := r.Header.Get("Sec-WebSocket-Key")
acceptKey := computeAcceptKey(key)
responseHeaders := "HTTP/1.1 101 Switching Protocols\r\n" +
"Upgrade: websocket\r\n" +
"Connection: Upgrade\r\n" +
"Sec-WebSocket-Accept: " + acceptKey + "\r\n\r\n"
conn.Write([]byte(responseHeaders))
// Simple print loop
for {
message, err := readMessage(conn)
if err != nil {
fmt.Println("Read error:", err)
break
}
fmt.Println("Received:", string(message))
if err := writeMessage(conn, message); err != nil {
fmt.Println("Write error:", err)
break
}
}
}
func computeAcceptKey(key string) string {
magic := "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
hash := sha1.Sum([]byte(key + magic))
return base64.StdEncoding.EncodeToString(hash[:])
}