下面由golang教程栏目给大家go使用websocket实现弹幕功能的方法,希望对需要的朋友有所帮助!
使用websocket协议,客户端发送一个消息,服务端广播到所有有效连接中。
主要思路:
1.封装*websocket.conn,用client结构表示一个客户端。
2.维持一个map[client]bool,表示有效的客户端映射,用于广播消息
3.除了处理websocket连接外,还要开启一个广播协程,监听客户端连接,断开,发弹幕事件。
推荐:《go语言教程》
主要的结构:
type client struct{ wsconnect *websocket.conn inchan chan []byte outchan chan []byte closechan chan byte name string //客户的名称 id string //客户id,唯一 mutex sync.mutex // 对closechan关闭上锁 isclosed bool // 防止closechan被关闭多次}type message struct { eventtype byte `json:"type"` // 0表示用户发布消息;1表示用户进入;2表示用户退出 name string `json:"name"` // 用户名称 message string `json:"message"` // 消息内容} clients = make(map [*util.client] bool) // 用户组映射 join = make(chan *util.client, 10) // 用户加入通道 leave = make(chan *util.client, 10) // 用户退出通道 message = make(chan message, 10) // 消息通道server端代码
package mainimport ( "encoding/json" "fmt" "github.com/gorilla/websocket" "gogin/server/util" "net/http")var( upgrader = websocket.upgrader{ // 允许跨域 checkorigin:func(r *http.request) bool{ return true }, } clients = make(map [*util.client] bool) // 用户组映射 join = make(chan *util.client, 10) // 用户加入通道 leave = make(chan *util.client, 10) // 用户退出通道 message = make(chan message, 10) // 消息通道)type message struct { eventtype byte `json:"type"` // 0表示用户发布消息;1表示用户进入;2表示用户退出 name string `json:"name"` // 用户名称 message string `json:"message"` // 消息内容}func wshandler(w http.responsewriter , r *http.request){ var( wsconn *websocket.conn err error client *util.client data []byte ) r.parseform() //返回一个map,并且赋值给r.form name := r.form["name"][0] id := r.form["id"][0] if wsconn , err = upgrader.upgrade(w,r,nil); err != nil{ return } if client , err = util.initconnection(wsconn); err != nil{ goto err } client.id = id client.name = name // 如果用户列表中没有该用户 if !clients[client] { join <- client } for { if data , err = client.readmessage();err != nil{ //一直读消息,没有消息就阻塞 goto err } var msg message msg.eventtype = 0 msg.name = client.name msg.message = string(data) message <- msg }err: leave<-client//这个客户断开 client.close()}func broadcaster() { for { select { // 消息通道中有消息则执行,否则堵塞 case msg := <-message: // 将数据编码成json形式,data是[]byte类型 // json.marshal()只会编码结构体中公开的属性(即大写字母开头的属性) data, err := json.marshal(msg) if err != nil { return } for client := range clients { if client.isclosed == true { leave<-client//这个客户断开 continue } // fmt.println("=======the json message is", string(data)) // 转换成字符串类型便于查看 if client.writemessage(data) != nil { continue //发送失败就跳过 } } // 有用户加入 case client := <-join: clients[client] = true // 将用户加入映射 // 将用户加入消息放入消息通道 var msg message msg.name = client.name msg.eventtype = 1 msg.message = fmt.sprintf("%s join in, there are %d preson in room", client.name, len(clients)) message <- msg // 有用户退出 case client := <-leave: // 如果该用户已经被删除 if !clients[client] { break } delete(clients, client) // 将用户从映射中删除 // 将用户退出消息放入消息通道 var msg message msg.name = client.name msg.eventtype = 2 msg.message = fmt.sprintf("%s leave, there are %d preson in room", clien
网站上有个视频播放为什么地址后面会加上这个呢cloud域名有价值吗?cloud域名需要实名制吗?学生阿里云服务器多少钱哪购买腾讯云服务器哪里便宜如何使用阿里云服务器建设网站腾讯云服务器需要备案么这个网站打不开请帮忙看一下什么情况链接无法打开-虚拟主机/数据库问题