網(wǎng)站首頁 編程語言 正文
使用socket和channel,實(shí)現(xiàn)簡單控制臺聊天室
這里使用socket和channel,演示在GO中如何編寫一個簡單網(wǎng)絡(luò)程序
功能分析
聊天室主要功能:用戶可以加入/離開聊天室;每個用戶發(fā)送的消息,廣播給所有人
聊天室分為客戶端和服務(wù)端,客戶端負(fù)責(zé)發(fā)送消息和打印服務(wù)器消息,服務(wù)器負(fù)責(zé)接收客戶端消息,并廣播給所有人
客戶端可以使用telnet程序
服務(wù)端是需要實(shí)現(xiàn)的。需要實(shí)現(xiàn)的功能,
- 如何保存多個客戶端的連接,管理連接的接入與斷開
- 如何接收和廣播客戶端消息
實(shí)現(xiàn)思路
通過功能分析,拆分為聊天室結(jié)構(gòu)體和客戶端結(jié)構(gòu)體
聊天室結(jié)構(gòu)體負(fù)責(zé)管理當(dāng)前接入的客戶端和廣播消息
客戶端結(jié)構(gòu)體負(fù)責(zé)管理socket連接和需要接收與發(fā)送的數(shù)據(jù)
客戶端連接/斷開時通知聊天室;客戶端發(fā)送的消息實(shí)際是轉(zhuǎn)發(fā)給聊天室,然后聊天室再廣播出去
完整代碼
package main import ( "bufio" "fmt" "log" "net" ) type Client struct { id string conn *net.Conn message chan string } type Hub struct { clients map[*Client]bool entering chan *Client leaving chan *Client messages chan string } func main() { hub := &Hub{ clients: make(map[*Client]bool), entering: make(chan *Client), leaving: make(chan *Client), messages: make(chan string), } listener, err := net.Listen("tcp", ":8000") if err != nil { log.Fatal(err) } go hub.broadcaster() for { conn, err := listener.Accept() if err != nil { log.Println(err) continue } go hub.handleConn(conn) } } func (hub *Hub) broadcaster() { for { select { case msg := <-hub.messages: for cli := range hub.clients { cli.message <- msg } case cli := <-hub.entering: hub.clients[cli] = true case cli := <-hub.leaving: delete(hub.clients, cli) } } } func (hub *Hub) handleConn(conn net.Conn) { defer conn.Close() ch := make(chan string) who := conn.RemoteAddr().String() client := &Client{who, &conn, ch} go hub.writeLoop(client) ch <- "welcome " + client.id hub.messages <- client.id + " join chat" hub.entering <- client hub.readLoop(client) hub.messages <- client.id + " has left" hub.leaving <- client } func (hub *Hub) writeLoop(client *Client) { for msg := range client.message { fmt.Fprintf(*client.conn, "%s\n", msg) } } func (hub *Hub) readLoop(client *Client) { input := bufio.NewScanner(*client.conn) for input.Scan() { hub.messages <- client.id + ": " + input.Text() } }
分析
實(shí)現(xiàn)的關(guān)鍵是封裝了客戶端通信channel,無論是遠(yuǎn)程發(fā)送過來的消息還是聊天室廣播的消息,都通過這個channel傳遞,且這個channel是綁定客戶端的
參考鏈接中,直接使用channel來定義客戶端type client chan<- string
,其實(shí)更能表達(dá)這一點(diǎn)
為了容易理解,這里將channel封裝為客戶端的一個通信管道,客戶端還可以有別的屬性,例如:id、連接和超時時間等
原文鏈接:https://www.cnblogs.com/snowsteps/p/15711223.html
相關(guān)推薦
- 2023-10-16 后端Long類型傳到前端精度丟失的問題
- 2022-07-08 一文詳解C++中運(yùn)算符的使用_C 語言
- 2022-02-28 Chrome控制臺提示“Slow network is detected. Fallback fon
- 2023-01-15 Android傳感器使用實(shí)例介紹_Android
- 2022-10-02 Flutter的鍵值存儲數(shù)據(jù)庫使用示例詳解_Android
- 2022-12-07 React?Context?變遷及背后實(shí)現(xiàn)原理詳解_React
- 2022-12-21 k8s安裝CICD?devtron過程詳解_云其它
- 2022-11-06 Python命令行參數(shù)解析包argparse的使用詳解_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支