websocket封裝
package edd_socket
import (
"time"
"log"
"encoding/json"
"golang.org/x/net/websocket"
)
type ws struct {
coon *websocket.Conn
}
//訊息體
type Message struct {
Data interface{} `json:"content"`
Type string `json:"type"`
TimeStamp int64 `json:"time_stamp"`
}
//使用者體
type User struct {
Uid string
conn *websocket.Conn
}
var (
member = make(map[string]*User)
uidMapWs = make(map[string]*websocket.Conn)
groupMapMember = make(map[string][]*User)
)
//例項化ws
func NewWS(wss *websocket.Conn) *ws {
return &ws{coon: wss}
}
//繫結uid和coon
func (this *ws) BindUid(uid string) {
client := User{Uid: uid,conn: this.coon}
member[uid] = &client
uidMapWs[uid] = this.coon
}
//是否線上
func (this *ws) IsOnline(uid string) bool {
_, exits := member[uid]
return exits
}
//斷開連線
func (this *ws) CloseUid(uid string) {
msg := Message{
Data: "離開房間",
Type: "del_user",
}
this.SendToAll(msg)
delete(member, uid)
delete(uidMapWs, uid)
this.coon.Close()
}
//群發訊息
func (this *ws) SendToAll(msg Message) {
msg.TimeStamp = time.Now().Unix()
sendMess, _ := json.Marshal(msg)
for k, v := range member {
if v.conn != this.coon {
if err := websocket.Message.Send(v.conn, string(sendMess)); err != nil {
delete(member, k)
delete(uidMapWs, k)
continue
}
}
}
}
//獲取當前組人數
func (this *ws) GetClientCountByGroup(groupName string) int {
return len(groupMapMember[groupName])
}
func (this *ws) GetClientByGroup(groupName string) []*User {
return groupMapMember[groupName]
}
//加入某個群
func (this *ws) JoinGroup(groupName, uid string) {
groupMapMember[groupName] = append(groupMapMember[groupName], member[uid])
}
//給指定群發訊息
func (this *ws) SendToGroup(groupName string, msg Message) {
msg.TimeStamp = time.Now().Unix()
sendMess, _ := json.Marshal(msg)
for k, v := range groupMapMember[groupName] {
if v.conn != this.coon {
if err := websocket.Message.Send(v.conn, string(sendMess)); err != nil {
kk := k + 1
groupMapMember[groupName] = append(groupMapMember[groupName][:k], groupMapMember[groupName][kk:]...)
continue
}
}
}
}
//離開某個群
func (this *ws) LeaveGroup(groupName, uid string) {
for k, v := range groupMapMember[groupName] {
if v.Uid == uid {
kk := k + 1
groupMapMember[groupName] = append(groupMapMember[groupName][:k], groupMapMember[groupName][kk:] ...)
break
}
}
}
//傳送給指定uid
func (this *ws) SendToUid(uid string, msg Message) {
toWsCoon := uidMapWs[uid]
msg.TimeStamp = time.Now().Unix()
sendMess, _ := json.Marshal(msg)
if err := websocket.Message.Send(toWsCoon, string(sendMess)); err != nil {
delete(member, uid)
log.Println(err)
}
}
//解析客戶端訊息
func (this *ws) GetMsg(msg *Message) error {
var reply string
var err error
if err = websocket.Message.Receive(this.coon, &reply); err == nil {
json.Unmarshal([]byte(reply), msg)
}
return err
}
使用:
package edd_socket
import (
"fmt"
"net/http"
"crypto/md5"
"encoding/hex"
"io"
"crypto/rand"
"encoding/base64"
"log"
"golang.org/x/net/websocket"
)
//獲取MD5字串
func getMd5String(s string) string {
h := md5.New()
h.Write([]byte(s))
return hex.EncodeToString(h.Sum(nil))
}
//用於將當前使用者資訊和當前websocket.conn關聯
//正式上線,可用資料庫使用者Id代替
func getUid() string {
b := make([]byte, 48)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return ""
}
return getMd5String(base64.URLEncoding.EncodeToString(b))
}
func Echo(ws *websocket.Conn) {
wss := NewWS(ws)
uid := getUid()
defer func() {
wss.CloseUid(uid)
}()
for {
var mess Message
if err := wss.GetMsg(&mess); err != nil {
//若當前socket接收不到訊息,則已掉線,主動退出for
fmt.Println(err)
break
}
switch mess.Type {
case "connect":
//連線準備,客戶端識別符號name和服務端識別符號繫結
wss.BindUid(uid)
msg := Message{
Data: mess.Data,
Type: "join_room",
}
wss.SendToAll(msg)
case "all":
//群發
msg := Message{
Data: mess.Data,
Type: "send_all",
}
wss.SendToAll(msg)
case "join_group":
//wss.JoinGroup("one", uid)
case "who":
}
}
}
func main() {
var port = "8022"
fmt.Println("listening port:" + port)
go func() {
http.Handle("/chat", websocket.Handler(Echo))
}()
if err := http.ListenAndServe(":"+port, nil); err != nil {
log.Fatal("ListenAndServer: ", err)
}
}
客戶端
var ws =new WebSocket(websocket_domain)
ws.onopen = function (res) {
ws.send(sendMessAll(name,"進入房間",'connect'))
};
ws.onmessage = function (res) {
var data = jQuery.parseJSON(res.data);
};
ws.onclose = function (res) {
console.log(res)
};
function sendMessAll(name, data, type) {
return JSON.stringify(
{
data: JSON.stringify({
name:name,
age:123
}),
type: type
}
)
}
歡迎指正我的開源地址
相關文章
- JS — websocket封裝JSWeb封裝
- 1_websocket工具封裝Web封裝
- WebSocket 封裝,vue3專案 拿來即用Web封裝Vue
- ai問答:vue3+pinia+WebSocket 封裝斷線重連(實戰)AIVueWeb封裝
- 【封裝那些事】 缺失封裝封裝
- 封裝封裝
- 【封裝小技巧】is 系列方法的封裝封裝
- 【JavaScript框架封裝】公共框架的封裝JavaScript框架封裝
- Sqlite封裝1-基本封裝-SqliteToolSQLite封裝
- Flutter 封裝:富文字 RichText 極簡封裝Flutter封裝
- Dapper的封裝、二次封裝、官方擴充套件包封裝,以及ADO.NET原生封裝APP封裝套件
- AVPlayer封裝封裝
- ajax 封裝封裝
- 封裝OCX封裝
- 封裝介面封裝
- sqlite封裝SQLite封裝
- java封裝Java封裝
- java 封裝Java封裝
- EventBus封裝封裝
- FMDB封裝封裝
- 5.1封裝封裝
- 09 #### 封裝封裝
- 【封裝小技巧】列表處理函式的封裝封裝函式
- Flutter MVP 封裝FlutterMVP封裝
- JavaScript 模組封裝JavaScript封裝
- JS功能封裝JS封裝
- ToolBar封裝策略封裝
- svg sprite 封裝SVG封裝
- request sdk 封裝封裝
- 09-封裝封裝
- Java(三)封裝Java封裝
- lua list 封裝封裝
- TS MQTT封裝MQQT封裝
- axios封裝iOS封裝
- 封裝axios封裝iOS
- weex 封裝actionSheetModule封裝
- 封裝xunsearch類封裝
- Arduino 封裝庫UI封裝