Collider 就是 WebRTC 的信令服务器,负责转发 SDP、ICE Candidate 和管理房间用户状态,但不处理实际音视频流。
👉 collider 不是生产级服务器,不安全、不稳定、不高并发。
👉 Google 官方也说了:仅供 demo,不推荐用于正式环境。
collidermain
main.go
// tls:布尔值,默认 true,表示是否启用 TLS(HTTPS)。
var tls = flag.Bool("tls", true, "whether TLS is used")
// port:整数值,默认 443,表示服务监听的端口。
var port = flag.Int("port", 443, "The TCP port that the server listens on")
// room-server:字符串,默认 "https://appr.tc",表示 房间服务器 的 URL。
var roomSrv = flag.String("room-server", "https://appr.tc", "The origin of the room server")
// 解析命令行传入的参数
flag.Parse()
// 打印
log.Printf("Starting collider: tls = %t, port = %d, room-server=%s", *tls, *port, *roomSrv)
// 创建一个 Collider 实例
c := collider.NewCollider(*roomSrv)
// 启动服务
c.Run(*port, *tls)
collider
collider.go
| 方法名 |
参数 |
说明 |
NewCollider(rs string) |
rs:房间服务器 URL |
创建 Collider 实例,初始化 roomTable 和 dashboard。 |
Run(p int, useTls bool) |
p:端口号,useTls:是否启用 TLS |
启动 HTTP/HTTPS + WebSocket 服务,阻塞主线程。 |
httpStatusHandler(w http.ResponseWriter, r *http.Request) |
HTTP 请求/响应对象 |
HTTP GET /status,返回服务状态 JSON(房间数、客户端数等)。 |
httpHandler(w http.ResponseWriter, r *http.Request) |
HTTP 请求/响应对象 |
HTTP POST/DELETE /ROOMID/CLIENTID,用于发送消息或删除客户端记录。 |
wsHandler(ws *websocket.Conn) |
WebSocket 连接对象 |
WebSocket 消息处理,包括:register 注册客户端,send 发送消息。 |
httpError(msg string, w http.ResponseWriter) |
错误消息,HTTP 响应对象 |
处理 HTTP 错误,返回 500 并记录到 dashboard。 |
wsError(msg string, ws *websocket.Conn) |
错误消息,WebSocket 连接对象 |
处理 WebSocket 错误,发送错误消息给客户端并记录到 dashboard。 |
dashboard.go
| 方法名 |
参数 |
返回值 |
作用说明 |
newDashboard() |
无 |
*dashboard |
创建并初始化一个新的 dashboard 实例,记录 startTime。 |
(db *dashboard) getReport(rs *roomTable) |
rs *roomTable |
statusReport |
获取当前服务状态报告,包括:服务运行时长、当前打开的 WebSocket 数量、累计 WebSocket 数量、WebSocket 错误数、HTTP 错误数。使用锁保证线程安全。 |
(db *dashboard) incrWs() |
无 |
无 |
WebSocket 新连接建立时调用,累计 totalWs 增加 1。线程安全。 |
(db *dashboard) onWsErr(err error) |
err error |
无 |
WebSocket 发生错误时调用,累计 wsErrs 增加 1。线程安全。 |
(db *dashboard) onHttpErr(err error) |
err error |
无 |
HTTP 请求发生错误时调用,累计 httpErrs 增加 1。线程安全。 |
roomTable.go
| 方法名 |
参数 |
返回值 |
作用说明 |
(rt *roomTable) room(id string) |
id:房间 ID |
*room |
获取指定房间,如果房间不存在则创建一个新的房间(线程安全)。 |
(rt *roomTable) roomLocked(id string) |
id:房间 ID |
*room |
与 room 类似,但假设调用方已经持有锁,不再重复加锁。 |
(rt *roomTable) remove(rid string, cid string) |
rid 房间 ID,cid 客户端 ID |
无 |
删除指定客户端,如果房间为空则删除房间(线程安全)。 |
(rt *roomTable) removeLocked(rid string, cid string) |
同上 |
无 |
与 remove 类似,但假设锁已持有。 |
(rt *roomTable) send(rid string, srcID string, msg string) |
rid 房间 ID,srcID 发送者 ID,msg 消息内容 |
error |
转发消息到指定房间,如果房间不存在则创建,调用房间的 send 方法。 |
(rt *roomTable) register(rid string, cid string, rwc io.ReadWriteCloser) |
rid 房间 ID,cid 客户端 ID,rwc WebSocket 连接 |
error |
将客户端注册到指定房间,如果房间不存在则创建。 |
(rt *roomTable) deregister(rid string, cid string) |
rid 房间 ID,cid 客户端 ID |
无 |
注销客户端的 WebSocket 注册,但保留客户端对象,等待超时后自动移除,以便用户可无缝重连。 |
(rt *roomTable) removeIfUnregistered(rid string, c *client) |
rid 房间 ID,客户端对象 |
无 |
超时检查函数,如果客户端在超时时间内未注册,则移除该客户端。 |
(rt *roomTable) wsCount() |
无 |
int |
返回当前所有房间中活跃 WebSocket 连接总数。 |
room.go
| 方法名 |
参数 |
返回值 |
作用说明 |
(rm *room) client(clientID string) |
客户端 ID |
*client, error |
获取房间内指定客户端,如果不存在且房间未满则创建新客户端;设置注册超时定时器,超时未注册则由父 roomTable 删除。 |
(rm *room) register(clientID string, rwc io.ReadWriteCloser) |
客户端 ID,WebSocket 连接对象 |
error |
将客户端绑定到 WebSocket 连接;注册后如果房间有其他客户端,则发送队列消息给新客户端。 |
(rm *room) send(srcClientID string, msg string) |
发送方客户端 ID,消息内容 |
error |
将消息发送给房间内另一客户端;如果另一客户端未加入,则将消息入队等待。 |
(rm *room) remove(clientID string) |
客户端 ID |
无 |
移除指定客户端,关闭连接;向房间服务器发送 BYE 请求;从 clients map 删除客户端。 |
(rm *room) empty() |
无 |
bool |
判断房间是否为空(没有客户端)。 |
(rm *room) wsCount() |
无 |
int |
统计房间内已注册的 WebSocket 客户端数量,用于全局统计。 |
client.go
| 方法 |
作用 |
newClient |
创建 client |
setTimer |
设置重连计时器(会停止旧 timer) |
register |
注册 WebSocket 连接 |
deregister |
清理 WebSocket 连接 |
registered |
是否已注册 WebSocket |
enqueue |
当前 client 出消息(发给别人)但对方不在线 → 缓存消息 |
sendQueued |
把队列消息发送给对方(在对方连接时调用) |
send |
对外发送消息(如果对方在线就直接发,否则缓存) |
messages.go
| 方法名 |
参数 |
作用说明 |
| sendServerMsg(w io.Writer, msg string) |
w: WebSocket writer、msg: 要发送的消息内容 |
构造 wsServerMsg{Msg: msg} 并发送给客户端(JSON 格式) |
| sendServerErr(w io.Writer, errMsg string) |
w: WebSocket writer、errMsg: 错误消息 |
构造 wsServerMsg{Error: errMsg} 并发送给客户端(JSON 格式) |
| send(w io.Writer, data interface{}) |
w: writer(通常是 websocket.Conn)data: 任意结构体 |
将结构体序列化成 JSON 写入 WebSocket;底层通用发送函数 |