接入websocket并实现最基础的文字通讯

一、完成webscoket协议

1.新建controller/chat.go 20、接入websocket并实现最基础的文字通讯 - 图1

2.在main的go中定义一个路由,形成映射关系 20、接入websocket并实现最基础的文字通讯 - 图2

二、实现controller/chat.go的Chat方法

首先下载webscoket相关包go get -u github.com/golang/net/webscoket 20、接入websocket并实现最基础的文字通讯 - 图3

websocket包下载指令go get github.com/gorilla/websocket 20、接入websocket并实现最基础的文字通讯 - 图4

下载 第三方集合包go get -u gopkg.in/fatih/set.v0 20、接入websocket并实现最基础的文字通讯 - 图5

  1. package controller
  2. import (
  3. "fmt"
  4. "github.com/gorilla/websocket"
  5. "gopkg.in/fatih/set.v0"
  6. "log"
  7. "net/http"
  8. "strconv"
  9. "sync"
  10. )
  11. // 本核心在于形成userid和Node的映射关系
  12. type Node struct {
  13. Conn *websocket.Conn
  14. //并行转串行,
  15. DataQueue chan []byte
  16. GroupSets set.Interface
  17. }
  18. // 映射关系表
  19. var clientMap map[int64]*Node = make(map[int64]*Node, 0)
  20. // 读写锁
  21. var rwlocker sync.RWMutex
  22. // ws://127.0.0.1/chat?id=1&token=xxxx
  23. func Chat(writer http.ResponseWriter,
  24. request *http.Request) {
  25. //todo 检验接入是否合法
  26. //checkToken(userId int64,token string)
  27. //request.URL.Query() 获取url中所有数据
  28. query := request.URL.Query()
  29. id := query.Get("id")
  30. token := query.Get("token")
  31. //获取的数据都是字符串,需要做整型
  32. userId, _ := strconv.ParseInt(id, 10, 64)
  33. isvalida := checkToken(userId, token)
  34. //如果isvalida=true
  35. //isvalida=false 这是一般的处理方法
  36. //在webscoket中有处理方法
  37. conn, err := (&websocket.Upgrader{
  38. CheckOrigin: func(r *http.Request) bool {
  39. return isvalida
  40. },
  41. }).Upgrade(writer, request, nil)
  42. //如果有错直接打印出来
  43. if err != nil {
  44. log.Println(err.Error())
  45. return
  46. }
  47. //todo 获得conn
  48. node := &Node{
  49. Conn: conn,
  50. DataQueue: make(chan []byte, 50),
  51. GroupSets: set.New(set.ThreadSafe),
  52. }
  53. //todo userid和node形成绑定关系
  54. rwlocker.Lock() //操作数据量比较大,所以添加了读写锁
  55. clientMap[userId] = node
  56. rwlocker.Unlock()
  57. //todo 完成发送逻辑,con
  58. go sendproc(node)
  59. //todo 完成接收逻辑
  60. go recvproc(node)
  61. //
  62. sendMsg(userId, []byte("hello,world!"))
  63. }
  64. // 发送协程
  65. func sendproc(node *Node) {
  66. for {
  67. select {
  68. case data := <-node.DataQueue:
  69. err := node.Conn.WriteMessage(websocket.TextMessage, data)
  70. if err != nil {
  71. log.Println(err.Error())
  72. return
  73. }
  74. }
  75. }
  76. }
  77. // 接收协程
  78. func recvproc(node *Node) {
  79. for {
  80. _, data, err := node.Conn.ReadMessage()
  81. if err != nil {
  82. log.Println(err.Error())
  83. return
  84. }
  85. //todo 对data进一步处理
  86. fmt.Printf("recv<=%s", data)
  87. }
  88. }
  89. // todo 发送消息
  90. func sendMsg(userId int64, msg []byte) {
  91. rwlocker.RLock() //读写锁为了保证并发的安全性
  92. node, ok := clientMap[userId]
  93. rwlocker.RUnlock()
  94. if ok {
  95. node.DataQueue <- msg
  96. }
  97. }
  98. // 检测是否有效
  99. func checkToken(userId int64, token string) bool {
  100. //从数据库里面查询并比对
  101. user := userService.Find(userId)
  102. return user.Token == token
  103. }

三、实现service/user.go的Find方法

20、接入websocket并实现最基础的文字通讯 - 图6

四、前端websocket初始化

20、接入websocket并实现最基础的文字通讯 - 图7

五、进行测试一下

20、接入websocket并实现最基础的文字通讯 - 图8

如上就是接入websocket成功