打造一款屬于自己的go語(yǔ)言socket框架4之session管理

前言:

上篇文章說(shuō)道我們?cè)趺赐ㄟ^(guò)不同的數(shù)據(jù)去調(diào)用框架中不同的函數(shù),在socket編程中,服務(wù)器做的不僅僅是接受信息,還需要推送消息,最典型的場(chǎng)景就是聊天室了,每當(dāng)一個(gè)客戶端發(fā)送一個(gè)一條消息,服務(wù)端就需要把這條消息,循環(huán)發(fā)送給其它所有客戶端。已經(jīng)把所有代碼整合了,希望給個(gè)星星支持一下 microSocket。

實(shí)現(xiàn)思路:

我們知道在go語(yǔ)言socket編程時(shí),服務(wù)端向客戶端發(fā)送信息只需要 調(diào)用 conn.write()即可,一個(gè)連接就對(duì)應(yīng)一個(gè)conn,每次服務(wù)端從一個(gè)客戶端消息的時(shí)候,想要推送給別的客戶端信息就需要?jiǎng)e的客戶端的coon,所以我們的解決思路就是

  1. 每次客戶端和服務(wù)端握手成功后,就把當(dāng)前的conn,保存到全局 協(xié)程安全的map里
  2. 當(dāng)客戶端與服務(wù)端斷開(kāi)連接的時(shí)候就把這個(gè)coon從map里面刪除

每次服務(wù)器要廣播全體的時(shí)候,就把當(dāng)前的 map遍歷一遍,一次推送就好了

代碼實(shí)現(xiàn):

每次連接成功的時(shí)候就把coon 封裝成一個(gè)session

for {
        //不斷地結(jié)束新的客戶端連接
        conn, err := tcpListen.Accept()
        if err != nil {
            log.Println(err)
            continue
        }
        //把conn封裝成一個(gè)session
        sess := NewSession(fd, conn)
        //把session 保存到sessionMaster
        this.SessionMaster.SetSession(fd, sess)
        fd++
        go this.connHandle(conn, sess)
    }

session 和sessionMaster的實(shí)現(xiàn)

//-------------------------------------------一個(gè)session代表一個(gè)連接------------------------------------------
type session struct {
    id    uint32
    con   net.Conn
    times int64
    lock  sync.Mutex
}

func NewSession(id uint32, con net.Conn) *session {
    return &session{
        id:    id,
        con:   con,
        times: time.Now().Unix(),
    }
}
//向conn寫(xiě)數(shù)據(jù)
func (this *session) write(msg string) error {
    this.lock.Lock()
    defer this.lock.Unlock()
    _ ,errs := this.con.Write([]byte(msg))
    return errs
}
//關(guān)閉conn
func (this *session)close(){
    this.con.Close()
}

//.......................................SESSION管理類.......................................

type SessionM struct {
    sessions map[uint32]*session
    num      uint32
    lock     sync.RWMutex
}

func NewSessonM() *SessionM {
    return &SessionM{
        sessions: make(map[uint32]*session),
        num:      0,
    }
}

func (this *SessionM) GetSessionById(id uint32) *session {
    if v, exit := this.sessions[id]; exit {
        return v
    }
    return nil
}

func (this *SessionM) SetSession(id uint32, sess *session) {
    this.lock.Lock()
    defer this.lock.Unlock()
    this.sessions[id] = sess
}

//關(guān)閉連接并刪除
func (this *SessionM) DelSessionById(id uint32) {
    this.lock.Lock()
    defer this.lock.Unlock()
    if v,exit := this.sessions[id];exit{
        v.con.Close()
    }
    delete(this.sessions, id)
}

func (this *SessionM) WriteByid(id uint32, msg string) bool {
    if v, exit := this.sessions[id]; exit {
        if err := v.write(msg); err != nil {
            this.DelSessionById(id)
            return false
        } else {
            return true
        }
    }
    return false
}
代碼解釋:
  1. 首先我們要封裝一個(gè)session類,一個(gè)session就對(duì)應(yīng)一個(gè)conn,大家可能發(fā)現(xiàn)到了,為什么conn.write
    我們要加鎖呢。原因也很簡(jiǎn)單,就是為了保證,同一時(shí)間,最多只會(huì)有一個(gè)協(xié)程向一個(gè)coon寫(xiě)數(shù)據(jù),如果有多個(gè)協(xié)程同時(shí)寫(xiě)的話,就會(huì)發(fā)生數(shù)據(jù)混亂,所以這里的鎖是很有必要的!
  2. 接下來(lái)就是sessionMaster類,服務(wù)端就是通過(guò)它來(lái)對(duì)所有客戶端的連接進(jìn)行操作,它的核心,其實(shí)就是一個(gè)sessions 的map,該map在刪除和插入新數(shù)據(jù)時(shí)都有加鎖處理,確保協(xié)程安全。當(dāng)服務(wù)端想要像客戶端推送消息的時(shí)候直接調(diào)用write方法就好了如下:
ser.SessionMaster.WriteByid(uint32(fd), "Hello")

總結(jié):

  1. 通過(guò)全局sessionMaster對(duì)所有客戶端的連接進(jìn)行統(tǒng)一管理,方便推送客戶端數(shù)據(jù)
  2. 每次對(duì)客戶端推送數(shù)據(jù)時(shí)必須要加鎖,不然數(shù)據(jù)可能會(huì)錯(cuò)亂

至此我們的socket框架分享,已經(jīng)差不多講完了,有什么不懂得,或者意見(jiàn)歡迎留言評(píng)論。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第一部分 Python基礎(chǔ)篇(80題) 1、為什么學(xué)習(xí)Python? Python相對(duì)于其他編程語(yǔ)言有很多優(yōu)點(diǎn): ...
    清清子衿木子水心閱讀 1,828評(píng)論 0 1
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評(píng)論 19 139
  • 養(yǎng)只貓,再養(yǎng)只狗 一只叫Siri 一只叫Google Hey Siri! Ok Google!
    魏鞍陽(yáng)閱讀 218評(píng)論 1 3
  • 接著講參加萌姐線上復(fù)盤(pán)課的感悟: 在萌姐的年度復(fù)盤(pán)課上我對(duì)可控時(shí)間又有了新一步的理解,以前總是覺(jué)得晚上跟著...
    lovent閱讀 133評(píng)論 0 0
  • 參加過(guò)很多群體性活動(dòng),比如:21天不抱怨活、30天腹肌訓(xùn)練、天天平板撐曬朋友圈、365天改變自己訓(xùn)練營(yíng)、每周讀一本...
    己未閱讀 606評(píng)論 4 6

友情鏈接更多精彩內(nèi)容