我正在try 实现WebSocket服务器using 100 standard library.

到目前为止,我的try 是这样的:

package main

import (
    "fmt"
    "net/http"

    "golang.org/x/net/websocket"
)

type Server struct {
    baseUri     string
    connections map[string][]*websocket.Conn
}

func initServer(baseUri string) *Server {
    return &Server{
        baseUri: baseUri,
    }
}

func (server *Server) handleConnections() {
    http.Handle("/ws", websocket.Handler(server.listenConnections))
    http.ListenAndServe(":3000", nil)
}

func (server *Server) listenConnections(ws *websocket.Conn) {
    fmt.Println("New connection established")
    for {
        fmt.Println("FOO")
    }
}

func main() {
    server := initServer("/ws")
    server.handleConnections()
}

try 使用多个WS客户端连接到ws://localhost:3000/ws时,我总是收到相同的错误:A 403-Forbidden. 我甚至试过了official doc's example米,但仍然能拿到.我是不是漏掉了什么明显的东西?类似于默认端口阻止或类似的?

提前谢谢您.

编辑:您可能希望使用不同的端口来重现该问题.在我的例子中使用3000,如果不可用,只会中断程序的执行.

编辑2:您可以使用像websocat和DO websocat 'ws://localhost:3000/ws'这样的客户端try 连接到服务器

推荐答案

我放弃了,但有了很好的洞察力: 如果你像我一样正在关注Anthony GG的walkthrough on creating a websocket server on Go from scratch,请不要这样做.视频已经过时了,虽然它给了我们一个很好的直觉来创建一个,但最好(也不要羞愧)学习使用大猩猩的网络插座库.

package main

import (
    "fmt"
    "net/http"
    "time"

    "github.com/gorilla/mux"
    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

type Server struct {
    baseUri     string
    connections map[string][]*websocket.Conn
    router      *mux.Router
    setup       *http.Server
}

func initServer(baseUri string) *Server {
    router := mux.NewRouter()
    return &Server{
        baseUri: baseUri,
        router:  router,
        setup: &http.Server{
            Handler:      router,
            Addr:         "127.0.0.1:8000",
            WriteTimeout: 15 * time.Second,
            ReadTimeout:  15 * time.Second,
        },
    }
}

func (server *Server) handleConnections() {
    server.router.HandleFunc("/ws/{var}", server.listenConnections)
    server.setup.ListenAndServe()
}

func (server *Server) listenConnections(w http.ResponseWriter, r *http.Request) {
    connection, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
        return
    }
    for {
        _, message, err := connection.ReadMessage()
        if err != nil {
            break
        }

        connection.WriteMessage(websocket.TextMessage, message)
        go messageHandler(message)
    }
    fmt.Println("Out of loop")
}

func messageHandler(message []byte) {
    fmt.Println(string(message))
}

func main() {
    server := initServer("/ws")
    server.handleConnections()
}

我还使用gorilla/mux来使用路径参数(不确定为什么http处理程序不能). 注意我是如何将http.Handle更改为mux.Router.HandleFunc的. 正如User@Cerise在 comments 中指出的那样,x/net/websocket包不在标准库中,但仅仅添加Origin头文件也不能解决原始问题.

希望这能跳过其他人像我一样学习围棋的一些令人头疼的问题.

Go相关问答推荐

将Go程序导出到WASM—构建约束排除所有Go文件

CGO如何转换为文件*类型

Go中的Slice[:1][0]与Slice[0]

使用!NOT运算符的Golang文本/模板多个条件

迭代字符串并用映射值替换原始字符串中的值的惯用方法

运行 Docker 容器 - X11 无法打开显示:0

Kusto Go API 从多个表查询

在golang二进制中嵌入SvelteKit

加载 docker 镜像失败

是否可以从 golang 中的参数推断类型?

如何在 Go 中编写示例测试?

在 .go 文件中运行一个函数和在 Go 模板中调用它有什么区别?

在 Go 中公开公共 JWK

如何仅提取时间作为持续时间

无法使用 Golang 扫描文件路径

使用 oklog/run 来自 Go 编译器的错误(无值)用作值

如何在 GORM 中获取字段值

Go 加密库创建的 PKCS1 公钥与openssl rsa ...之间的区别

Go Fyne 禁用 HSplit 调整大小?

如何在 Windows 中使用 github.com/AllenDang/giu 和 github.com/gordonklaus/portaudio 构建 GO 程序