今天浅浅的了解一下websocket
1、什么是websocket
WebSocket 是一种网络通信协议,它允许在单个TCP连接上进行全双工通信。这意味着服务器和客户端可以在任何时候发送数据,而无需等待对方的响应。WebSocket 通常用于实时应用程序,如聊天应用、在线游戏和实时数据传输。
2、在go中如何使用websocket
在go中可以使用gorilla/websocket库来实现websocket
2.1 下载gorilla/websocket
go get github.com/gorilla/websocket
2.2基本使用
package main
import (
"github.com/gorilla/websocket"
"log"
"net/http"
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
func handler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
return
}
for {
messageType, p, err := conn.ReadMessage()
if err != nil {
log.Println(err)
return
}
if err := conn.WriteMessage(messageType, p); err != nil {
log.Println(err)
return
}
}
}
func main() {
// 创建HTTP服务器
http.HandleFunc("/ws", handler)
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
运行以上代码之后我们使用apipost来测试我们的接口,打开apipost创建一个websocket,在地址中输入ws://localhost:8080/ws,点击连接下方就会显示连接成功。如下图
当我们输入值,并且点击发送时,数据就会传入服务端,并且服务端会将此数据返回给客户端。比如我们在内容框中使用text格式发送—你好go-websocket,服务端就会返回当前发送的值。
这里使用最基础的内容,要深入了解可以去gorilla/websocket的GitHub仓库了解
https://github.com/gorilla/websocket
2.3将以上代码浅浅改造一下
package main
import (
"fmt"
"github.com/gorilla/websocket"
"log"
"net/http"
)
// 创建公共管道用于广播消息--缓存1
var publicchannl = make(chan []byte, 1)
var readpublic <-chan []byte = publicchannl //只读
var writepublic chan<- []byte = publicchannl //只写
var Map = make(map[string]*User) //保存所有连接的用户
type User struct {
IP string
Content string
Conn *websocket.Conn
}
func NewUser(Ip string, conn *websocket.Conn, content string) *User {
return &User{
IP: Ip,
Content: content,
Conn: conn,
}
}
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func main() {
// 创建HTTP服务器
http.HandleFunc("/ws", handleWebSocket)
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
// 升级HTTP连接为WebSocket连接
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
//创建实例
user := NewUser(conn.RemoteAddr().String(), conn, "")
//添加用户
Map[user.IP] = user
//广播
go func() {
for {
p := <-readpublic
for _, v := range Map {
v.Conn.WriteMessage(1, p)
}
}
}()
// 处理WebSocket连接
for {
// 读取消息
_, p, err := user.Conn.ReadMessage()
if err != nil {
fmt.Println(user.IP, ":", "断开连接")
delete(Map, user.IP)
return
}
user.Content = string(p)
fmt.Println(user.IP, ":", user.Content)
str := user.IP + ":" + string(p)
writepublic <- []byte(str)
}
}
2.4 再加入一点js ,这里使用的是vue
<script setup>
// import Main from "@/components/HomePage/main.vue";
import {onBeforeMount, reactive, ref} from "vue";
const d = reactive({
i: "",
ms: [],
ws: null,
})
let ws = ref(null);
onBeforeMount(() => {
ws = new WebSocket("ws://localhost:8080/ws")
ws.addEventListener('message', handleMessage)
})
const sendmessage = () => {
ws.send(d.i)
}
const handleMessage = (event) => {
d.ms.push(event.data)
}
</script>
<template>
<!-- <!– 为文章主页面–>-->
<!-- <Main></Main>-->
<!-- <router-view></router-view>-->
<el-container>
<el-main style="height: 400px">
<div class="l" style="border:black solid 1px ;width: 400px;height: 500px">
<div style="width: 400px;background-color:white" v-for="item in d.ms.length ">
{{d.ms[item-1]}}
</div>
</div>
</el-main>
<el-footer>
<el-input v-model="d.i" placeholder="输入框"></el-input>
<el-button type="primary" @click="sendmessage">发送信息</el-button>
</el-footer>
</el-container>
</template>
<style scoped>
</style>
当我们在apipost中发送text时,网页也能实时收到广播的消息
以上是我今天学习websocket 写的一个类似于实时聊天的一个小功能。