add websocket
This commit is contained in:
9
go.mod
9
go.mod
@@ -6,8 +6,9 @@ require (
|
|||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/go-ini/ini v1.67.0
|
github.com/go-ini/ini v1.67.0
|
||||||
|
github.com/gorilla/websocket v1.5.1
|
||||||
github.com/jinzhu/gorm v1.9.16
|
github.com/jinzhu/gorm v1.9.16
|
||||||
golang.org/x/crypto v0.9.0
|
golang.org/x/crypto v0.14.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -31,9 +32,9 @@ require (
|
|||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
golang.org/x/net v0.10.0 // indirect
|
golang.org/x/net v0.17.0 // indirect
|
||||||
golang.org/x/sys v0.8.0 // indirect
|
golang.org/x/sys v0.13.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
golang.org/x/text v0.13.0 // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
18
go.sum
18
go.sum
@@ -40,6 +40,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
|||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||||
|
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||||
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
|
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
|
||||||
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
|
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
@@ -89,24 +91,24 @@ golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
|||||||
113
handlers/ClientManager.go
Normal file
113
handlers/ClientManager.go
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
// Package ws is to define a websocket server and client connect.
|
||||||
|
// Author: Arthur Zhang
|
||||||
|
// Create Date: 20190101
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClientManager is a websocket manager
|
||||||
|
type ClientManager struct {
|
||||||
|
Clients map[*Client]bool
|
||||||
|
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 an object for websocket message which is mapped to json type
|
||||||
|
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[*Client]bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start is to start a ws server
|
||||||
|
func (manager *ClientManager) Start() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case conn := <-manager.Register:
|
||||||
|
manager.Clients[conn] = true
|
||||||
|
jsonMessage, _ := json.Marshal(&Message{Content: "/A new socket has connected."})
|
||||||
|
manager.Send(jsonMessage, conn)
|
||||||
|
case conn := <-manager.Unregister:
|
||||||
|
if _, ok := manager.Clients[conn]; ok {
|
||||||
|
close(conn.Send)
|
||||||
|
delete(manager.Clients, conn)
|
||||||
|
jsonMessage, _ := json.Marshal(&Message{Content: "/A socket has disconnected."})
|
||||||
|
manager.Send(jsonMessage, conn)
|
||||||
|
}
|
||||||
|
case message := <-manager.Broadcast:
|
||||||
|
for conn := range manager.Clients {
|
||||||
|
select {
|
||||||
|
case conn.Send <- message:
|
||||||
|
default:
|
||||||
|
close(conn.Send)
|
||||||
|
delete(manager.Clients, conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send is to send ws message to ws client
|
||||||
|
func (manager *ClientManager) Send(message []byte, ignore *Client) {
|
||||||
|
for conn := range manager.Clients {
|
||||||
|
if conn != ignore {
|
||||||
|
conn.Send <- message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) Read() {
|
||||||
|
defer func() {
|
||||||
|
Manager.Unregister <- c
|
||||||
|
c.Socket.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
_, message, err := c.Socket.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
Manager.Unregister <- c
|
||||||
|
c.Socket.Close()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
jsonMessage, _ := json.Marshal(&Message{Sender: c.ID, Content: string(message)})
|
||||||
|
Manager.Broadcast <- jsonMessage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Socket.WriteMessage(websocket.TextMessage, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
main.go
40
main.go
@@ -2,11 +2,14 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"go_blog/conf"
|
"go_blog/conf"
|
||||||
"go_blog/handlers"
|
"go_blog/handlers"
|
||||||
"go_blog/models"
|
"go_blog/models"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
@@ -63,6 +66,43 @@ func main() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 注册WebSocket路由
|
||||||
|
r.GET("/ws", WebSocketHandler)
|
||||||
|
|
||||||
r.POST("/login", handlers.UsersLoginHandler)
|
r.POST("/login", handlers.UsersLoginHandler)
|
||||||
r.Run(":8080")
|
r.Run(":8080")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WebSocketHandler(c *gin.Context) {
|
||||||
|
// 获取WebSocket连接
|
||||||
|
//ws, err := websocket.Upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
|
|
||||||
|
var upGrader = websocket.Upgrader{
|
||||||
|
CheckOrigin: func(r *http.Request) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理WebSocket消息
|
||||||
|
for {
|
||||||
|
messageType, p, err := ws.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("messageType:", messageType)
|
||||||
|
fmt.Println("p:", string(p))
|
||||||
|
|
||||||
|
// 输出WebSocket消息内容
|
||||||
|
c.Writer.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭WebSocket连接
|
||||||
|
ws.Close()
|
||||||
|
}
|
||||||
|
|||||||
43
templates/list.tmpl
Normal file
43
templates/list.tmpl
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>My Blog</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{ range $key, $val := . -}}
|
||||||
|
{{ $key }}:{{ $val }}
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<a
|
||||||
|
href="<?php $this->permalink() ?>"><?php $this->title() ?></a>
|
||||||
|
</h2>
|
||||||
|
<ul class="post-meta">
|
||||||
|
<li itemprop="author" itemscope itemtype="http://schema.org/Person"><?php _e('作者: '); ?><a
|
||||||
|
itemprop="name" href="<?php $this->author->permalink(); ?>"
|
||||||
|
rel="author"><?php $this->author(); ?></a></li>
|
||||||
|
<li><?php _e('时间: '); ?>
|
||||||
|
<time datetime="<?php $this->date('c'); ?>" itemprop="datePublished"><?php $this->date(); ?></time>
|
||||||
|
</li>
|
||||||
|
<li><?php _e('分类: '); ?><?php $this->category(','); ?></li>
|
||||||
|
<li itemprop="interactionCount">
|
||||||
|
<a itemprop="discussionUrl"
|
||||||
|
href="<?php $this->permalink() ?>#comments"><?php $this->commentsNum('评论', '1 条评论', '%d 条评论'); ?></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="post-content" itemprop="articleBody">
|
||||||
|
<?php $this->content('- 阅读剩余部分 -'); ?>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<?php endwhile; ?>
|
||||||
|
|
||||||
|
<?php $this->pageNav('« 前一页', '后一页 »'); ?>
|
||||||
|
</div><!-- end #main-->
|
||||||
|
|
||||||
|
<?php $this->need('sidebar.php'); ?>
|
||||||
|
<?php $this->need('footer.php'); ?>
|
||||||
Reference in New Issue
Block a user