接入websocket并实现最基础的文字通讯
一、完成webscoket协议
1.新建controller/chat.go
2.在main的go中定义一个路由,形成映射关系
二、实现controller/chat.go的Chat方法
首先下载webscoket相关包go get -u github.com/golang/net/webscoket
websocket包下载指令go get github.com/gorilla/websocket
下载 第三方集合包go get -u gopkg.in/fatih/set.v0
package controller
import (
"fmt"
"github.com/gorilla/websocket"
"gopkg.in/fatih/set.v0"
"log"
"net/http"
"strconv"
"sync"
)
// 本核心在于形成userid和Node的映射关系
type Node struct {
Conn *websocket.Conn
//并行转串行,
DataQueue chan []byte
GroupSets set.Interface
}
// 映射关系表
var clientMap map[int64]*Node = make(map[int64]*Node, 0)
// 读写锁
var rwlocker sync.RWMutex
// ws://127.0.0.1/chat?id=1&token=xxxx
func Chat(writer http.ResponseWriter,
request *http.Request) {
//todo 检验接入是否合法
//checkToken(userId int64,token string)
//request.URL.Query() 获取url中所有数据
query := request.URL.Query()
id := query.Get("id")
token := query.Get("token")
//获取的数据都是字符串,需要做整型
userId, _ := strconv.ParseInt(id, 10, 64)
isvalida := checkToken(userId, token)
//如果isvalida=true
//isvalida=false 这是一般的处理方法
//在webscoket中有处理方法
conn, err := (&websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return isvalida
},
}).Upgrade(writer, request, nil)
//如果有错直接打印出来
if err != nil {
log.Println(err.Error())
return
}
//todo 获得conn
node := &Node{
Conn: conn,
DataQueue: make(chan []byte, 50),
GroupSets: set.New(set.ThreadSafe),
}
//todo userid和node形成绑定关系
rwlocker.Lock() //操作数据量比较大,所以添加了读写锁
clientMap[userId] = node
rwlocker.Unlock()
//todo 完成发送逻辑,con
go sendproc(node)
//todo 完成接收逻辑
go recvproc(node)
//
sendMsg(userId, []byte("hello,world!"))
}
// 发送协程
func sendproc(node *Node) {
for {
select {
case data := <-node.DataQueue:
err := node.Conn.WriteMessage(websocket.TextMessage, data)
if err != nil {
log.Println(err.Error())
return
}
}
}
}
// 接收协程
func recvproc(node *Node) {
for {
_, data, err := node.Conn.ReadMessage()
if err != nil {
log.Println(err.Error())
return
}
//todo 对data进一步处理
fmt.Printf("recv<=%s", data)
}
}
// todo 发送消息
func sendMsg(userId int64, msg []byte) {
rwlocker.RLock() //读写锁为了保证并发的安全性
node, ok := clientMap[userId]
rwlocker.RUnlock()
if ok {
node.DataQueue <- msg
}
}
// 检测是否有效
func checkToken(userId int64, token string) bool {
//从数据库里面查询并比对
user := userService.Find(userId)
return user.Token == token
}
三、实现service/user.go的Find方法
四、前端websocket初始化
五、进行测试一下
如上就是接入websocket成功