此处固定是发给clients["1"]客户端消息,也就是发给自己。而且不是线程安全的!!!
package main
import (
"github.com/gorilla/websocket"
"net/http"
"log"
"fmt"
)
type Message struct {
Msg string // 消息内容
ToId string // 目标用户的id
FromId string // 发送消息的用户的id
}
var clients = make(map[string] *websocket.Conn) //连接客户端(在线的),其中map的键为用户id
var pushMsgs = make(chan Message, 1000) //要推送的消息
// 配置upgrader
var upgrader = websocket.Upgrader{
// 允许跨域
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func main() {
// 创建一个简单的文件服务器
fs := http.FileServer(http.Dir("../public"))
http.Handle("/", fs)
// 配置websocket路由
http.HandleFunc("/ws", WsConns)
// 收听传入的聊天信息
go ToMessage()
// 在本地主机端口上启动并记录所有错误
log.Println("http server started on :8000")
err := http.ListenAndServe(":8000", nil)
if err != nil {
log.Fatal("ListenAndServe error:", err)
}
}
func WsConns(w http.ResponseWriter, r *http.Request) {
//完成握手升级
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Fatal(err)
}
// 确保在函数返回时关闭连接
defer ws.Close()
// 提示下机
defer fmt.Printf("——%v下机了——\n", ws.RemoteAddr())
// 注册新客户端
clients["1"] = ws
//fmt.Println(clients["1"].)
// 输出ip
fmt.Println("当前登录用户:", ws.RemoteAddr())
for {
var msg Message
err := ws.ReadJSON(&msg)
if err != nil {
log.Printf("error1: %v", err)
// 若接收消息错误,则将该发送消息的用户的websocket连接去掉
delete(clients, msg.FromId)
}
//将接收到的消息写入消息channel
pushMsgs <- msg
}
}
func ToMessage() {
for {
// 从消息推送channel获取消息
msg := <- pushMsgs
// 发送给指定的客户端
err := clients["1"].WriteJSON(msg)
if err != nil {
log.Printf("error2: %v", err)
clients["1"].Close()
delete(clients, "1")
}
}
}