Vue写一个简易客户端
<template>
<div class="view">
<input type="text" v-model="msg"><button @click="send">发言</button>
<div class="chat-title">聊天记录:</div>
<div v-for="(item,index) in msgList" :key="index" class="chat-box">{{item}}</div>
</div>
</template>
<script>
export default {
data() {
return {
msg: '',
ws: '',
msgList: []
}
},
methods: {
send() {
this.ws.send(this.msg)
//this.ws.send(JSON.stringify({msg: this.msg}))
this.msg = ''
}
},
mounted() {
this.ws = new WebSocket('ws://127.0.0.1:3000/ping')
// 连接打开时触发
this.ws.onopen = () => {
console.log("Connection open ...")
}
// 接收到消息时触发
this.ws.onmessage = (evt) => {
console.log(evt)
this.msgList.push(evt.data)
}
this.ws.onclose = () => {
console.log('Connection close !!!')
}
},
// 关闭连接
beforeDestroy() {
this.ws.close()
}
}
</script>
<style scoped>
.view{
width: 600px;
margin: 0 auto;
background-color:aliceblue;
height: 500px;
text-align: center;
padding-top: 80px;
}
.chat-title{
text-align:left;
margin-left:100px;
margin-top:50px;
}
.chat-box{
background-color: white;
width: 400px;
margin: 0 auto;
}
</style>
复制代码
- data中定义三变量:msg发送消息载体,msgList接收服务端消息,ws为websocket对象。
- vue生命周期mounted中页面渲染完成,就new一个websocket对象赋给ws,监听了三个事件。onmessage中当服务端有数据推送过来就push到msgList中,留给页面处理。
- vue生命周期beforeDestory中,假如页面组件销毁就关闭ws连接。
- 按钮事件send中,将input输入框中的数据msg发送给后端,其中我注释掉的代码是以json字符串的方式传输。
Go 服务端代码
首先进入main函数,完成对gin路由的初始
package main
import "go-websocket/route"
func main() {
route.Init()
}
复制代码
再看路由代码
package route
import (
"go-websocket/controller/ws"
"github.com/gin-gonic/gin"
)
// Init 路由初始化
func Init() {
router := gin.Default()
router.GET("/ping", ws.Ping)
router.Run(":3000")
}
复制代码
当前端页面渲染完成,就会来连接后端,不出意外就会进入这边的处理器函数ws.Ping
package ws
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
var upGrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
// type data struct {
// Msg string `json:"msg"`
// }
// Ping webSocket请求Ping 返回pong
func Ping(c *gin.Context) {
//升级get请求为webSocket协议
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
defer ws.Close()
for {
// 读取ws中的数据
mt, message, err := ws.ReadMessage()
if err != nil {
// 客户端关闭连接时也会进入
fmt.Println(err)
break
}
// msg := &data{}
// json.Unmarshal(message, msg)
// fmt.Println(msg)
fmt.Println(mt)
fmt.Println(message)
fmt.Println(string(message))
// 如果客户端发送ping就返回pong,否则数据原封不动返还给客户端
if string(message) == "ping" {
message = []byte("pong")
}
// 写入ws数据 二进制返回
err = ws.WriteMessage(mt, message)
// 返回JSON字符串,借助gin的gin.H实现
// v := gin.H{"message": msg}
// err = ws.WriteJSON(v)
if err != nil {
break
}
}
}
复制代码
代码中有详细的注释,就不一一介绍了,其中被我注释掉的代码是服务端以json字符串的方式接收和发送数据。打印接收到的数据是以十进制显示的utf-8编码。
其中int类型的mt我不清楚是什么意思,我就跟踪了下源码。
// The message types are defined in RFC 6455, section 11.8.
const (
// TextMessage denotes a text data message. The text message payload is
// interpreted as UTF-8 encoded text data.
TextMessage = 1
// BinaryMessage denotes a binary data message.
BinaryMessage = 2
// CloseMessage denotes a close control message. The optional message
// payload contains a numeric code and text. Use the FormatCloseMessage
// function to format a close message payload.
CloseMessage = 8
// PingMessage denotes a ping control message. The optional message payload
// is UTF-8 encoded text.
PingMessage = 9
// PongMessage denotes a pong control message. The optional message payload
// is UTF-8 encoded text.
PongMessage = 10
)
复制代码