
本文旨在帮助开发者解决在使用 Golang 构建 WebSocket 服务时,Chrome 浏览器出现 "WebSocket connection failed: Unexpected response code: 400" 错误的问题。通过提供修改后的服务端和客户端代码,阐述了跨域请求导致该错误的原因,并提供了将 HTML 文件托管在 Golang 服务器上的解决方案。
问题分析
当 Chrome 浏览器报告 "WebSocket connection failed: Unexpected response code: 400" 错误时,通常是因为浏览器检测到跨域请求,并认为客户端没有足够的权限访问 WebSocket 服务。 默认情况下,浏览器会阻止从一个域加载的网页去请求另一个域的资源,这被称为同源策略。
解决方案
解决此问题的关键是将 HTML 页面也托管在 Golang 服务器上,确保 WebSocket 连接与提供 HTML 页面的源同源。
1. 修改 Golang 服务端代码
立即学习“go语言免费学习笔记(深入)”;
修改 main.go 文件,使其能够同时提供静态文件服务和 WebSocket 服务。以下是修改后的代码:
package main
import (
"fmt"
"log"
"net/http"
"golang.org/x/net/websocket"
)
func Echo(ws *websocket.Conn) {
var err error
for {
var reply string
if err = websocket.Message.Receive(ws, &reply); err != nil {
fmt.Println("Can't receive")
break
}
fmt.Println("Received back from client: " + reply)
msg := "Received: " + reply
fmt.Println("Sending to client: " + msg)
if err = websocket.Message.Send(ws, msg); err != nil {
fmt.Println("Can't send")
break
}
}
}
func main() {
http.Handle("/", http.FileServer(http.Dir("."))) // 提供静态文件服务
http.Handle("/socket", websocket.Handler(Echo)) // WebSocket 服务
log.Println("serving")
if err := http.ListenAndServe(":1234", nil); err != nil {
log.Fatal("ListenAndServe:", err)
}
}关键修改在于添加了 http.Handle("/", http.FileServer(http.Dir("."))) 这一行代码。它将根路径 / 映射到当前目录 (.),允许服务器提供当前目录下的静态文件,包括 HTML 文件。同时,将WebSocket服务的路径修改为 /socket。
2. 修改 HTML 客户端代码
修改 HTML 文件,使其连接到正确的 WebSocket 服务路径。以下是修改后的 index.html 文件:
WebSocket Echo Test
关键修改在于将 wsuri 的值修改为 "ws://127.0.0.1:1234/socket",与服务端代码中 WebSocket 服务的路径相匹配。
3. 目录结构
确保 index.html 文件与 main.go 文件位于同一目录下。例如:
. ├── index.html └── main.go
4. 运行程序
- 保存 main.go 和 index.html 文件。
- 在终端中,进入包含这两个文件的目录。
- 运行 go run main.go 命令启动服务器。
- 在 Chrome 浏览器中打开 http://127.0.0.1:1234/,即可访问 HTML 页面并建立 WebSocket 连接。
注意事项
- 确保安装了 golang.org/x/net/websocket 包。如果没有安装,可以使用 go get golang.org/x/net/websocket 命令安装。
- 如果仍然遇到问题,请检查浏览器的开发者工具,查看是否有其他错误信息。
- 在生产环境中,建议使用更健壮的静态文件服务器,例如 Nginx 或 Apache。
总结
通过将 HTML 页面托管在 Golang 服务器上,可以有效解决 Chrome 浏览器中 WebSocket 连接失败的 400 错误。 这种方法避免了跨域请求问题,确保客户端能够成功连接到 WebSocket 服务。 同时,需要注意WebSocket服务的路径配置,确保客户端和服务器端的配置一致。










