💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
~~~ package main import ( "fmt" "golang.org/x/net/websocket" "net/http" "runtime" "strconv" "strings" "sync" "time" ) var list map[int]map[*websocket.Conn]*websocket.Conn //所属聊天室里的连接 (map[int] 保存的是聊天室id) var ch map[int]chan []byte //加入聊天室后接收的信息 var msg map[int][][]byte //加入聊天室前接收的信息 var mu sync.Mutex func svrConnHandler(conn *websocket.Conn) { r := conn.Request() r.ParseForm() fGroupid := r.Form["groupid"][0] //聊天室Id groupid, _ := strconv.Atoi(fGroupid) // fUserid := r.Form["userid"][0] //用户Id userid, _ := strconv.Atoi(fUserid) // name := r.Form["name"][0] //用户名称 _, ok := list[groupid] if !ok { //初始化聊天室 list[groupid] = make(map[*websocket.Conn]*websocket.Conn, 500) ch[groupid] = make(chan []byte, 500) msg[groupid] = make([][]byte, 0, 500) } //TODO : 断线重连后, 又读取了一次历史数据(是否在定义一个message2方法, 让第二次连接的访问这个方法? 或者每次断线重连的时候清空之前显示的消息) //获取历史数据(视频直播聊天需求:要求新加入的用户也能获取之前的聊天记录) go func() { mu.Lock() //加锁, 防止在读取历史数据时, 有用户发送消息 list[groupid][conn] = conn for _, v := range msg[groupid] { conn.Write(v) } mu.Unlock() }() //接收客户端消息 go func() { var content [1024]byte for { n, err := conn.Read(content[:]) if err != nil { delete(list[groupid], conn) conn.Close() break } if n > 0 { //string(content[:]) 是 string 类型没错,只是这个 string 有 1024 个字符(后面 1020 个字符都是 0x00)。 if string(content[:n]) == string("ping www.51websocket.cn") { content = [1024]byte{} continue } content2 := append([]byte(fmt.Sprint(userid, ":::", name, ":::")), content[:n]...) ch[groupid] <- content2 content = [1024]byte{} } } }() //向客户端发送消息 if !ok { for { select { case content := <-ch[groupid]: mu.Lock() message := strings.Split(string(content), ":::") msg[groupid] = append(msg[groupid], []byte("<span class='name'>"+message[1]+":"+"</span>"+message[2])) for _, v := range list[groupid] { v.Write([]byte("<span class='name'>" + message[1] + ":" + "</span>" + message[2])) } mu.Unlock() /* 将用户留言保存到数据库 go func() { usermsg, _ := strconv.Atoi(message[0]) zdbmodel.InsertMessage(groupid, usermsg, message[1], message[2]) }() */ } } //<--向客户端发送消息--> } else { for { time.Sleep(time.Second * 60 * 60) } } } func main() { list = make(map[int]map[*websocket.Conn]*websocket.Conn, 100) ch = make(map[int]chan []byte, 10) msg = make(map[int][][]byte, 100) http.Handle("/message", websocket.Handler(svrConnHandler)) err := http.ListenAndServe(":8095", nil) SimplePanic(err) } func SimplePanic(err error) { if err != nil { _, file, line, _ := runtime.Caller(1) fmt.Println(file, line, err) runtime.Goexit() } } ~~~