成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

構建一個即時消息應用(五):實時消息

開發 后端
對于實時消息,我們將使用 服務器發送事件。這是一個打開的連接,我們可以在其中傳輸數據流。我們會有個端點,用戶會在其中訂閱發送給他的所有消息。

[[345206]]

本文是該系列的第五篇。

對于實時消息,我們將使用 服務器發送事件Server-Sent Events。這是一個打開的連接,我們可以在其中傳輸數據流。我們會有個端點,用戶會在其中訂閱發送給他的所有消息。

消息戶端

在 HTTP 部分之前,讓我們先編寫一個映射map ,讓所有客戶端都監聽消息。 像這樣全局初始化:

  1. type MessageClient struct { 
  2.     Messages chan Message 
  3.     UserID   string 
  4.  
  5. var messageClients sync.Map 

已創建的新消息

還記得在 上一篇文章 中,當我們創建這條消息時,我們留下了一個 “TODO” 注釋。在那里,我們將使用這個函數來調度一個 goroutine。

  1. go messageCreated(message) 

把這行代碼插入到我們留注釋的位置。

  1. func messageCreated(message Message) error { 
  2.     if err := db.QueryRow(` 
  3.         SELECT user_id FROM participants 
  4.         WHERE user_id != $1 and conversation_id = $2 
  5.     `, message.UserID, message.ConversationID). 
  6.     Scan(&message.ReceiverID); err != nil { 
  7.         return err 
  8.     } 
  9.  
  10.     go broadcastMessage(message) 
  11.  
  12.     return nil 
  13.  
  14. func broadcastMessage(message Message) { 
  15.     messageClients.Range(func(key, _ interface{}) bool { 
  16.         client := key.(*MessageClient) 
  17.         if client.UserID == message.ReceiverID { 
  18.             client.Messages <- message 
  19.         } 
  20.         return true 
  21.     }) 

該函數查詢接收者 ID(其他參與者 ID),并將消息發送給所有客戶端。

訂閱消息

讓我們轉到 main() 函數并添加以下路由:

  1. router.HandleFunc("GET""/api/messages", guard(subscribeToMessages)) 

此端點處理 /api/messages 上的 GET 請求。請求應該是一個 EventSource 連接。它用一個事件流響應,其中的數據是 JSON 格式的。

  1. func subscribeToMessages(w http.ResponseWriter, r *http.Request) { 
  2.     if a := r.Header.Get("Accept"); !strings.Contains(a, "text/event-stream") { 
  3.         http.Error(w, "This endpoint requires an EventSource connection", http.StatusNotAcceptable) 
  4.         return 
  5.     } 
  6.  
  7.     f, ok := w.(http.Flusher) 
  8.     if !ok { 
  9.         respondError(w, errors.New("streaming unsupported")) 
  10.         return 
  11.     } 
  12.  
  13.     ctx := r.Context() 
  14.     authUserID := ctx.Value(keyAuthUserID).(string) 
  15.  
  16.     h := w.Header() 
  17.     h.Set("Cache-Control""no-cache"
  18.     h.Set("Connection""keep-alive"
  19.     h.Set("Content-Type""text/event-stream"
  20.  
  21.     messages := make(chan Message) 
  22.     defer close(messages) 
  23.  
  24.     client := &MessageClient{Messages: messages, UserID: authUserID} 
  25.     messageClients.Store(client, nil) 
  26.     defer messageClients.Delete(client) 
  27.  
  28.     for { 
  29.         select { 
  30.         case <-ctx.Done(): 
  31.             return 
  32.         case message := <-messages: 
  33.             if b, err := json.Marshal(message); err != nil { 
  34.                 log.Printf("could not marshall message: %v\n", err) 
  35.                 fmt.Fprintf(w, "event: error\ndata: %v\n\n", err) 
  36.             } else { 
  37.                 fmt.Fprintf(w, "data: %s\n\n", b) 
  38.             } 
  39.             f.Flush() 
  40.         } 
  41.     } 

首先,它檢查請求頭是否正確,并檢查服務器是否支持流式傳輸。我們創建一個消息通道,用它來構建一個客戶端,并將其存儲在客戶端映射中。每當創建新消息時,它都會進入這個通道,因此我們可以通過 for-select 循環從中讀取。

服務器發送事件Server-Sent Events使用以下格式發送數據:

  1. data: some data here\n\n 

我們以 JSON 格式發送:

  1. data: {"foo":"bar"}\n\n 

我們使用 fmt.Fprintf() 以這種格式寫入響應寫入器writter,并在循環的每次迭代中刷新數據。

這個循環會一直運行,直到使用請求上下文關閉連接為止。我們延遲了通道的關閉和客戶端的刪除,因此,當循環結束時,通道將被關閉,客戶端不會收到更多的消息。

注意,服務器發送事件Server-Sent Events(EventSource)的 JavaScript API 不支持設置自定義請求頭😒,所以我們不能設置 Authorization: Bearer <token>。這就是為什么 guard() 中間件也會從 URL 查詢字符串中讀取令牌的原因。


實時消息部分到此結束。我想說的是,這就是后端的全部內容。但是為了編寫前端代碼,我將再增加一個登錄端點:一個僅用于開發的登錄。

 

 

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2020-10-09 12:45:19

創建消息即時消息編程語言

2019-09-29 15:25:13

CockroachDBGoJavaScript

2019-10-28 20:12:40

OAuthGuard中間件編程語言

2020-03-31 12:21:20

JSON即時消息編程語言

2020-10-12 09:20:13

即時消息Access頁面編程語言

2020-10-19 16:20:38

即時消息Conversatio編程語言

2020-10-16 14:40:20

即時消息Home頁面編程語言

2020-10-10 20:51:10

即時消息編程語言

2021-03-25 08:29:33

SpringBootWebSocket即時消息

2023-08-14 08:01:12

websocket8g用戶

2015-03-18 15:37:19

社交APP場景

2011-10-19 09:30:23

jQuery

2024-02-01 12:54:00

RustWebSocket消息代理

2023-11-30 08:34:29

批量消息消息隊列

2021-12-03 00:02:01

通訊工具即時

2010-05-24 09:51:37

System Cent

2023-03-27 08:33:32

2022-08-30 11:41:53

網絡攻擊木馬

2009-06-29 09:06:42

微軟Web版MSN

2021-05-10 15:05:18

消息通信本地網絡
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产欧美视频一区二区三区 | 成人av在线网站 | 国产女人与拘做视频免费 | 精品毛片视频 | 日韩激情网 | 久久久99国产精品免费 | 国产污视频在线 | 久久久网| 91影片 | 久久国产成人 | 日本精品一区二区三区在线观看 | 日韩国产中文字幕 | 久久久久久免费毛片精品 | 天堂网中文 | 日本在线免费看最新的电影 | 亚洲国产成人在线视频 | 日韩在线一区二区三区 | 成年人在线播放 | 国产欧美精品一区二区 | www.男人天堂.com | 91精品成人久久 | 春色av| www日韩高清| 男人天堂网址 | 精品免费观看 | 极品一区| 成年人免费网站 | 亚洲国产成人久久综合一区,久久久国产99 | 久久久一二三 | www.久久久久久久久久久久 | 国产精彩视频在线观看 | 亚洲精品久久久久久下一站 | 精品国产欧美 | 国产亚洲欧美在线视频 | 区一区二区三在线观看 | 亚洲一区二区三区福利 | 久久久久国产精品一区 | 99久久视频 | 亚洲综合久久精品 | 成人a免费| 欧美亚洲视频 |