這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
設計思路:每個websocket允許的串連都是有時間限制的,逾時後服務端會自動中斷連線,那麼長串連就在服務端發出中斷連線資訊後用戶端檢測斷開資訊再次發起串連請求,中間再通過握手資訊確保用戶端同伺服器處於串連狀態。
設計結構:
[plain] view plain copy
- type Longsocket struct {
- Ws *websocket.Conn
- writeCh chan []byte
- readCh chan []byte
- ShakeHand bool
- Url string
- Protocol string
- Origin string
- BufferSize int
- Status int
- mu sync.Mutex
- }
長串連通過`writeCh`通道主動向串連方發送訊息,通過`ReadCh`通道讀取串連中的資訊,設定`ShakeHand`來確定是否要發送握手資訊,Status用以標識串連狀態。
通過WriteLoop來發送握手資訊,同時監聽`WriteCh`通道,轉寄通道裡的訊息。
[plain] view plain copy
- //call func with a gorouting, it will send shake hands message to service to make sure self is ok
- //if you want to send message call func 'Write', and the case writeCh will be vaild
- func (l *Longsocket) WriteLoop() {
- defer func() {
- if err := recover(); err != nil {
- //fmt.Println("writeloop", err)
- }
- }()
-
- for {
- errCount := 0
- if l.Status != STATUS_CONNECT {
- break
- }
- select {
- case <-time.After(time.Second * time.Duration(SHAKE_HANDS_FREQUENCY)):
- if l.ShakeHand {
- _, err := l.Ws.Write([]byte(SHAKE_HANDS_MSG))
- if err != nil {
- errCount++
- }
- }
- case msg := <-l.writeCh:
- _, err := l.Ws.Write(msg)
- if err != nil {
- errCount++
- }
- }
-
- if errCount != 0 {
- break
- }
- }
- l.Close()
- }
通過ReadLoop來接受資訊,同時將訊息轉寄到`ReadCh`通道內。
[plain] view plain copy
- //read message form socket and write them to readCh
- func (l *Longsocket) ReadLoop() {
- defer func() {
- if err := recover(); err != nil {
- //fmt.Println("readloop", err)
- }
- }()
-
- for {
- if l.Status != STATUS_CONNECT {
- break
- }
- buf := make([]byte, l.BufferSize)
- n, err := l.Ws.Read(buf)
- if err != nil {
- break
- }
-
- if n > 0 {
- l.readCh <- buf[0:n]
- }
- }
- l.Close()
- }
然後可以通過Read函數將訊息轉寄到形如
type dealmsg func([]byte, *Longsocket) error
的函數中去做相應的訊息處理,當然你也可以通過Longsocket參數發送相應的處理訊息。
源碼已上傳githup如下,其中有demo供參考。
https://github.com/qianlnk/longsocket