gin websocket 一对一聊天
时间:2022-07-25
本文章向大家介绍gin websocket 一对一聊天,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
依赖包
github.com/gin-gonic/gin
github.com/gorilla/websocket
代码
创建ws/ws.go
package ws
import (
"encoding/json"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"log"
"net/http"
)
// ClientManager is a websocket manager
type ClientManager struct {
Clients map[string]*Client
Broadcast chan []byte
Register chan *Client
Unregister chan *Client
}
// Client is a websocket client
type Client struct {
ID string
Socket *websocket.Conn
Send chan []byte
}
// Message is return msg
type Message struct {
Sender string `json:"sender,omitempty"`
Recipient string `json:"recipient,omitempty"`
Content string `json:"content,omitempty"`
}
// Manager define a ws server manager
var Manager = ClientManager{
Broadcast: make(chan []byte),
Register: make(chan *Client),
Unregister: make(chan *Client),
Clients: make(map[string]*Client),
}
// Start is 项目运行前, 协程开启start -> go Manager.Start()
func (manager *ClientManager) Start() {
for {
log.Println("<---管道通信--->")
select {
case conn := <-Manager.Register:
log.Printf("新用户加入:%v", conn.ID)
Manager.Clients[conn.ID] = conn
jsonMessage, _ := json.Marshal(&Message{Content: "Successful connection to socket service"})
conn.Send <- jsonMessage
case conn := <-Manager.Unregister:
log.Printf("用户离开:%v", conn.ID)
if _, ok := Manager.Clients[conn.ID]; ok {
jsonMessage, _ := json.Marshal(&Message{Content: "A socket has disconnected"})
conn.Send <- jsonMessage
close(conn.Send)
delete(Manager.Clients, conn.ID)
}
case message := <-Manager.Broadcast:
MessageStruct :=Message{}
json.Unmarshal(message, &MessageStruct)
for id, conn := range Manager.Clients {
if id!=creatId(MessageStruct.Recipient,MessageStruct.Sender){
continue
}
select {
case conn.Send <- message:
default:
close(conn.Send)
delete(Manager.Clients, conn.ID)
}
}
}
}
}
func creatId(uid,touid string) string {
return uid+"_"+touid
}
func (c *Client) Read() {
defer func() {
Manager.Unregister <- c
c.Socket.Close()
}()
for {
c.Socket.PongHandler()
_, message, err := c.Socket.ReadMessage()
if err != nil {
Manager.Unregister <- c
c.Socket.Close()
break
}
log.Printf("读取到客户端的信息:%s", string(message))
Manager.Broadcast <- message
}
}
func (c *Client) Write() {
defer func() {
c.Socket.Close()
}()
for {
select {
case message, ok := <-c.Send:
if !ok {
c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
return
}
log.Printf("发送到到客户端的信息:%s", string(message))
c.Socket.WriteMessage(websocket.TextMessage, message)
}
}
}
//TestHandler socket 连接 中间件 作用:升级协议,用户验证,自定义信息等
func WsHandler(c *gin.Context) {
uid := c.Query("uid")
touid := c.Query("to_uid")
conn, err := (&websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}).Upgrade(c.Writer, c.Request, nil)
if err != nil {
http.NotFound(c.Writer, c.Request)
return
}
//可以添加用户信息验证
client := &Client{
ID: creatId(uid,touid),
Socket: conn,
Send: make(chan []byte),
}
Manager.Register <- client
go client.Read()
go client.Write()
}
创建main.go
package main
import (
"github.com/gin-gonic/gin"
"im/ws"
)
//server
func main() {
gin.SetMode(gin.ReleaseMode) //线上环境
go ws.Manager.Start()
r := gin.Default()
r.GET("/ws",ws.WsHandler)
r.GET("/pong", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run(":8282") // listen and serve on 0.0.0.0:8080
}
运行服务端
go run mian.go
创建client.html
<html>
<head>
<title>Golang Chat</title>
<script src="http://libs.baidu.com/jquery/1.4.2/jquery.min.js"></script>
<meta charset="UTF-8" />
<script type="text/javascript">
$(function() {
function getUrlParam(name)
{
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
var r = window.location.search.substr(1).match(reg); //匹配目标参数
if (r!=null) return unescape(r[2]); return null; //返回参数值
}
var conn;
var msg = $("#msg");
var log = $("#log");
uid=getUrlParam("uid");
to_uid=getUrlParam("to_uid");
function appendLog(msg) {
var d = log[0]
var doScroll = d.scrollTop == d.scrollHeight - d.clientHeight;
msg.appendTo(log)
if (doScroll) {
d.scrollTop = d.scrollHeight - d.clientHeight;
}
}
$("#form").submit(function() {
if (!conn) {
return false;
}
if (!msg.val()) {
return false;
}
var json = {"sender":uid,"recipient":to_uid,"content":msg.val()}; //创建对象;
var jsonStr = JSON.stringify(json); //转为JSON字符串
conn.send(jsonStr);
msg.val("");
return false
});
if (window["WebSocket"]) {
conn = new WebSocket("ws://localhost:8282/ws?uid="+uid+"&to_uid="+to_uid);
conn.onclose = function(evt) {
appendLog($("<div><b>Connection Closed.</b></div>"))
}
conn.onmessage = function(evt) {
appendLog($("<div/>").text(evt.data))
}
} else {
appendLog($("<div><b>WebSockets Not Support.</b></div>"))
}
});
</script>
<style type="text/css">
html {
overflow: hidden;
}
body {
overflow: hidden;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
background: gray;
}
#log {
background: white;
margin: 0;
padding: 0.5em 0.5em 0.5em 0.5em;
position: absolute;
top: 0.5em;
left: 0.5em;
right: 0.5em;
bottom: 3em;
overflow: auto;
}
#form {
padding: 0 0.5em 0 0.5em;
margin: 0;
position: absolute;
bottom: 1em;
left: 0px;
width: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div id="log"></div>
<form id="form">
<input type="submit" value="发送" />
<input type="text" id="msg" size="64"/>
</form>
</body>
</html>
自己搭建nginx或apache等web服务,分别在两个窗口运行
http://localhost/client.html?...
http://localhost/client.html?...
这样就可以聊天了
- ASP.NET MVC三个重要的描述对象:ParameterDescriptor
- Ngxtop-Nginx日志实时分析利器
- 数据在内存中的存储
- 数据抓取与利用行为的不正当竞争法规制
- python学习手册-爬爬那些年咱没见过的校花图片
- 正则表达式游戏的答案
- .NET Core的日志[2]:将日志输出到控制台
- 2017年高等教育十大战略性技术(二)
- 通过实例模拟ASP.NET MVC的Model绑定机制:数组
- 《全球贸易信息动态》
- .NET Core的日志[3]:将日志写入Debug窗口
- Code2Cloud:比ALM中断更大
- .NET Core的日志[4]:将日志写入EventLog
- 微信小程序不行了?看小马哥带你忆童年
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法