Golang基于WebSocket实现简易聊天室:代码解析与运行指南
本文分享了使用Golang实现简易WebSocket聊天室的完整过程。内容包含服务端的核心广播逻辑、前端网页客户端交互代码以及命令行测试工具,帮助开发者快速理解Websocket在Go语言中的双向通信应用。
实现目标与原理
本示例旨在展示如何利用Go语言标准库 net/http 配合第三方 websocket 包,建立一个支持多用户连接的实时聊天系统。核心机制包括:建立连接时分配唯一ID并广播欢迎信息;接收消息后遍历连接列表进行转发(排除发送者自身);断开连接时清理资源并通知其他用户。
环境准备
由于使用了早期版本的 websocket 实现,首先需要获取依赖包。在终端执行以下命令:
go get code.google.com/p/go.net/websocket
请确保网络通畅以拉取旧版仓库。若当前 Go 版本较高且无法访问该仓库,可考虑将 import 路径替换为社区维护的镜像(如 github.com/gorilla/websocket),但需注意后续代码中 API 的差异。
第1步:实现服务端核心逻辑
服务端负责监听端口、处理 HTTP 升级请求以及管理所有在线客户端。我们将聊天室的主要逻辑封装在 ChatroomServer 函数中。
1.1 连接管理与广播
服务端使用 container/list 维护所有活跃的 WebSocket 连接。当新连接进入时,生成 ID 并存入列表;消息广播时遍历该列表向所有客户端推送数据。
- 目的:管理用户状态并实现群发功能。
- 关键动作:
-ChatroomServer中调用conns.PushBack(ws)加入房间。
-SendMessage函数遍历链表,调用io.WriteString发送消息给除发送者外的所有节点。
1.2 启动服务
在 main 函数中注册路由:
/chatroom:映射到 websocket handler,用于实际通信。/:返回静态 HTML 页面,提供浏览器入口。- 监听端口:
:6611。
第2步:浏览器客户端界面
为了方便测试,我们直接在服务端返回一个简单的 HTML/JS 页面。页面内置了 jQuery 和原生 WebSocket API。
关键参数说明:
- 连接地址:
ws://127.0.0.1:6611/chatroom。 - 消息格式:输入文本后自动附加换行符
'\n'发送给服务器。 - UI 逻辑:收到消息后追加至
#log区域并自动滚动到底部。
var ws = new WebSocket("ws://127.0.0.1:6611/chatroom");
// ... 省略事件监听 ...
ws.send($('#msg').val()+"\n");
第3步:命令行客户端测试
除了浏览器,我们可以编写一个简单的 Go 命令行程序来模拟另一个聊天气泡,验证双端通信。这有助于在不打开浏览器的情况下测试后台服务稳定性。
操作流程:
- 建立连接:使用
websocket.Dial指定 URL 和 Origin。 - 并发读取:启动 Goroutine 读取标准输入,每行写入 WebSocket。
- 主循环接收:主循环持续从 WebSocket 读取服务端下发的消息。
origin := "http://127.0.0.1:6611/"
url := "ws://127.0.0.1:6611/chatroom"
ws, err := websocket.Dial(url, "", origin)
完整源码参考
以下是合并后的服务端代码及对应的 HTML 模板结构。请注意,此代码使用了较老的 code.google.com 包路径,仅作为学习 WebSocket 协议在 Golang 中实现逻辑的参考。
package main
import (
"fmt"
"io"
"bufio"
"net/http"
"code.google.com/p/go.net/websocket"
"container/list"
)
var connid int
var conns *list.List
func ChatroomServer(ws *websocket.Conn) {
defer ws.Close()
connid++
id := connid
fmt.Printf("connection id: %d\n", id)
item := conns.PushBack(ws)
defer conns.Remove(item)
name := fmt.Sprintf("user%d", id)
SendMessage(nil, fmt.Sprintf("welcome %s join\n", name))
r := bufio.NewReader(ws)
for {
data, err := r.ReadBytes('\n')
if err != nil {
fmt.Printf("disconnected id: %d\n", id)
SendMessage(item, fmt.Sprintf("%s offline\n", name))
break
}
fmt.Printf("%s: %s", name, data)
SendMessage(item, fmt.Sprintf("%s\t> %s", name, data))
}
}
func SendMessage(self *list.Element, data string) {
for item := conns.Front(); item != nil; item = item.Next() {
ws, ok := item.Value.(*websocket.Conn)
if !ok {
panic("item not *websocket.Conn")
}
if item == self {
continue
}
io.WriteString(ws, data)
}
}
func Client(w http.ResponseWriter, r *http.Request) {
html := `<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>golang websocket chatroom</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
var ws = new WebSocket("ws://127.0.0.1:6611/chatroom");
// ... (此处省略前端JS详细代码,见上文第2步说明) ...
</script>
</head>
<body>
<div id="log" style="height: 300px;overflow-y: scroll;border: 1px solid #CCC;"></div>
<div>
<form id="msgform">
<input type="text" id="msg" size="60" />
</form>
</div>
</body>
</html>`
io.WriteString(w, html)
}
func main() {
fmt.Printf(`Welcome chatroom server!`)
connid = 0
conns = list.New()
http.Handle("/chatroom", websocket.Handler(ChatroomServer));
http.HandleFunc("/", Client);
err := http.ListenAndServe(":6611", nil);
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}
运行与排错
- 启动服务:运行编译后的二进制文件,终端应显示
Welcome chatroom server!并无报错输出。 - 访问测试:浏览器打开
http://127.0.0.1:6611,观察控制台是否触发onopen事件。 - 跨域注意:原始代码中设置了固定的
Origin。如果在非127.0.0.1:6611下部署,需调整Client中 JS 的 WS URL 或服务端的 Origin 检查逻辑(注:原代码未显式拦截 Origin,依赖底层默认行为)。
以上就是Golang基于WebSocket实现的简易聊天室程序的详细内容,更多关于Golang WebSocket开发的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









