Go語言--廣播式并發聊天服務器

實現功能

  1. 每個客戶端上線,服務端可以向其他客戶端廣播上線信息;
  2. 發送的消息可以廣播給其他在線的客戶
  3. 支持改名
  4. 支持客戶端主動退出
  5. 支持通過who查找當前在線的用戶
  6. 超時退出

流程

在這里插入圖片描述

變量

  • 用戶結構體 保存用戶的管道,用戶名以及網絡地址信息
type Client struct {C    chan string //用于發送數據的管道Name string      //用戶名Addr string      //網絡地址
}
  • 保存在線用戶的map表
var onlineMap map[string]Client
  • 消息通道
var message = make(chan string)

主協程

  • 監聽客戶端的連接請求listener, err := net.Listen("tcp", "127.0.0.1:8000")
  • 當客戶端有消息發送,就向當前用戶列表中所有在線用戶轉發消息go Manager()
  • 接受客戶端的請求conn, err1 := listener.Accept()
  • 處理用戶連接go HandleConn(conn)
func main() {//監聽listener, err := net.Listen("tcp", "127.0.0.1:8000")if err != nil {fmt.Println("net.Listen.err=", err)return}defer listener.Close()//新開一個協程,轉發消息,只要有消息,就遍歷map,給每個成員發送消息go Manager()//主協程,循環阻塞等待用戶連接for {conn, err1 := listener.Accept()if err1 != nil {fmt.Println("listener.Accept.err1=", err1)continue}//處理用戶連接go HandleConn(conn)}}

處理用戶連接子協程

  • 獲取客戶端的網絡地址cliAddr := conn.RemoteAddr().String()
  • 創建一個用戶結構體,默認:用戶名和網絡地址一樣cli := Client{make(chan string), cliAddr, cliAddr},加入map表
  • 給客戶端發送信息go WriteMsgToClient(cli, conn)
  • 廣播某個人在線message <- MakeMsg(cli, "login")
  • 提示當前用戶 cli.C <- MakeMsg(cli, "I am here")
  • 判斷用戶狀態isQuit hasData
  • 接收用戶的請求,查看當前用戶who,改名rename,發送消息message
func HandleConn(conn net.Conn) {cliAddr := conn.RemoteAddr().String()cli := Client{make(chan string), cliAddr, cliAddr}//把結構體添加到maponlineMap[cliAddr] = cli//新開一個協程,給客戶端發送信息go WriteMsgToClient(cli, conn)//廣播某個人在線message <- MakeMsg(cli, "login")//提示當前用戶cli.C <- MakeMsg(cli, "I am here")isQuit := make(chan bool) //對方是否主動退出hasData := make(chan bool) //對方是否有數據//新開一個協程,接收用戶的請求go func() {buf := make([]byte, 2048)for {n, err := conn.Read(buf)if n == 0 {//對方斷開或者出問題isQuit <- truefmt.Println("conn.Read.err=", err)return}msg := string(buf[:n-1])if len(msg) == 3 && msg == "who" {//遍歷map,給當前用戶發送所有成員conn.Write([]byte("user list:\n"))for _, tmp := range onlineMap {msg := tmp.Addr + ":" + tmp.Name + "\n"conn.Write([]byte(msg))}} else if len(msg) >= 8 && msg[:6] == "rename" {name := strings.Split(msg, "|")[1]cli.Name = nameonlineMap[cliAddr] = cliconn.Write([]byte("rename ok\n"))} else {message <- MakeMsg(cli, msg)}hasData <- true //代表有數據}}()for {//通過select檢測channel的流動select {case <-isQuit:delete(onlineMap, cliAddr)           //當前用戶從map移除message <- MakeMsg(cli, "login out") //廣播誰下線了returncase <-hasData:case <-time.After(60 * time.Second):delete(onlineMap, cliAddr)message <- MakeMsg(cli, "time out leave out")return}}}

給客戶端發送信息

func WriteMsgToClient(cli Client, conn net.Conn) {for msg := range cli.C {conn.Write([]byte(msg + "\n"))}}

發送消息

func MakeMsg(cli Client, msg string) (buf string) {buf = "[" + cli.Addr + "]" + cli.Name + ":" + msgreturn
}

轉發消息子協程

有消息到來就進行廣播

  • 給map分配空間onlineMap = make(map[string]Client)
  • 遍歷在線用戶列表,轉發消息;沒有消息之前message通道會阻塞
func Manager() {//給map分配空間onlineMap = make(map[string]Client)for {msg := <-message //沒有消息前,會阻塞for _, cli := range onlineMap {cli.C <- msg}}
}

設計到的知識點

  1. 網絡編程,監聽客戶端連接,處理連接請求,發送轉發消息等
  2. map,切片,結構體數據,通道.
  3. 通過select檢測channel的流動
  4. 并發編程,開辟子協程處理當前請求等
  5. 超時判斷

效果展示

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/45606.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45606.shtml
英文地址,請注明出處:http://en.pswp.cn/web/45606.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ARM功耗管理之功耗數據與功耗收益評估

安全之安全(security)博客目錄導讀 思考&#xff1a;功耗數據如何測試&#xff1f;功耗曲線&#xff1f;功耗收益評估&#xff1f; UPF的全稱是Unified Power Format&#xff0c;其作用是把功耗設計意圖&#xff08;power intent&#xff09;傳遞給EDA工具&#xff0c; 從而幫…

vscode OpenCV環境搭建

cmake 官網https://cmake.org/files/ 環境變量D:\Program Files\CMake\bin w64devkit 官網https://github.com/skeeto/w64devkit/tags 環境變量D:\Program Files\w64devkit\bin minGW32-make 拷貝并重命名為make OpenCV 在執行完后&#xff0c;把關于python的都給取消勾選…

mybatis-plus映射mysql的json類型的字段

一、對json里面內容建立實體類 Data AllArgsConstructor NoArgsConstructor public class RouteMetaEntity {private String title;private Boolean affix;private Boolean isAlwaysShow; }二、主類做映射 TableField(typeHandler JacksonTypeHandler.class)private RouteMe…

Codeforces Round 958 (Div. 2)補題

文章目錄 A題 (拆分多集)B題(獲得多數票)C題&#xff08;固定 OR 的遞增序列&#xff09; A題 (拆分多集) 本題在賽時卡的時間比較久&#xff0c;把這題想復雜了&#xff0c;導致WA了兩次。后來看明白之后就是將n每次轉換成k-1個1&#xff0c;到最后分不出來k-1個1直接一次就能…

Hive的基本操作(查詢)

1、基礎查詢 基本語法 select 字段列表|表達式|子查詢 from 表(子查詢|視圖|臨時表|普通表) where [not] 條件A and|or 條件B --先&#xff1a;面向原始行進行篩選 group by 字段A[,字段B,...] > 分組【去重處理】 having 聚合條件(非原始字段條件) --再&#x…

JMeter案例分享:通過數據驗證的錯誤,說說CSV數據文件設置中的線程共享模式

前言 用過JMeter參數化的小伙伴&#xff0c;想必對CSV Data Set Config非常熟悉。大家平時更關注變量名稱&#xff0c;是否忽略首行等參數&#xff0c;其余的一般都使用默認值。然而我最近遇到一個未按照我的預想讀取數據的案例&#xff0c;原因就出在最后一個參數“線程共享模…

深度學習中激活函數的演變與應用:一個綜述

摘要 本文全面回顧了深度學習中激活函數的發展歷程,從早期的Sigmoid和Tanh函數,到廣泛應用的ReLU系列,再到近期提出的Swish、Mish和GeLU等新型激活函數。深入分析了各類激活函數的數學表達、特點優勢、局限性以及在典型模型中的應用情況。通過系統的對比分析,本文探討了激…

樹莓派配置vsftpd主動模式

sudo apt-get install vsftpd /etc/vsftpd.conf anonymous_enableNO # 禁用匿名用戶 local_enableYES # 允許本地用戶登錄 write_enableYES # 允許修改權限 #chroot_local_userYES # 將用戶限制在其主目錄 systemctl restart vsftpd sudo adduser ftpuser sudo pa…

詳解MySQL中的遞歸查詢

MySQL中的遞歸查詢主要通過WITH RECURSIVE語句來實現&#xff0c;這在處理具有層級關系或樹形結構的數據時非常有用。下面將通過一個具體的例子來詳細解釋如何在MySQL中使用遞歸查詢。 示例場景 假設我們有一個部門表&#xff08;departments&#xff09;&#xff0c;其中包含…

昇思訓練營打卡第二十五天(RNN實現情感分類)

RNN&#xff0c;即循環神經網絡&#xff08;Recurrent Neural Network&#xff09;&#xff0c;是一種深度學習模型&#xff0c;特別適用于處理序列數據。以下是對RNN的簡要介紹&#xff1a; RNN的特點&#xff1a; 記憶性&#xff1a;與傳統的前饋神經網絡不同&#xff0c;R…

老板新招的牛人,竟然用1天搭建了一套完整的倉庫管理系統!

倉儲管理系統是什么&#xff1f; 倉儲管理系統&#xff08;WMS&#xff09;是一個全面的軟件解決方案&#xff0c;旨在幫助企業優化倉庫管理流程、管理和控制日常倉庫運營。通過數學模型和信息手段&#xff0c;對倉庫管理的各個環節進行優化和調控&#xff0c;涵蓋了從貨物入庫…

使用網關和Spring Security進行認證和授權

個人名片 &#x1f393;作者簡介&#xff1a;java領域優質創作者 &#x1f310;個人主頁&#xff1a;碼農阿豪 &#x1f4de;工作室&#xff1a;新空間代碼工作室&#xff08;提供各種軟件服務&#xff09; &#x1f48c;個人郵箱&#xff1a;[2435024119qq.com] &#x1f4f1…

jquery發送jsonp請求

使用 jQuery 發送 JSONP 請求相對來說比較簡單&#xff0c;以下是示例代碼&#xff1a; $.ajax({url: "http://example.com/data",dataType: "jsonp",jsonp: "callback",jsonpCallback: "myCallback" }).done(function(response) {//…

Linux命令更新-sort 和 uniq 命令

簡介 sort 和 uniq 都是 Linux 系統中常用的文本處理命令。 sort 命令用于對文件內容進行排序。 uniq 命令用于去除文件中重復出現的行。 1. sort 命令 命令格式 sort [選項] [文件]選項&#xff1a; -n: 按照數字進行排序 -r: 反向排序 -c: 統計每個元素出現的次數 -…

怎么錄制視頻?電腦錄制,試試這3種方法

在數字化快速發展的時代&#xff0c;視頻已經成為我們傳遞信息、分享生活、表達情感的重要載體。每一個人都希望自己能夠掌握視頻錄制技巧&#xff0c;輕松駕馭影像的力量&#xff0c;創造出屬于自己的視覺盛宴。 那么&#xff0c;怎么錄制視頻呢&#xff1f;首先選擇一款好用…

vue腳手架配置代理請求

在 Vue 腳手架中&#xff0c;可以通過配置vue.config.js文件來設置代理請求&#xff0c;以解決跨域問題或實現其他代理需求。以下是兩種常見的配置方式&#xff1a; 方法一&#xff1a; 在vue.config.js中添加如下配置&#xff1a; module.exports {devServer: {proxy: http…

《信息與電腦(理論版)》是什么級別的期刊?是正規期刊嗎?能評職稱嗎?

問題解答 問&#xff1a;《信息與電腦(理論版)》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知網收錄的正規學術期刊。 問&#xff1a;《信息與電腦(理論版)》級別&#xff1f; 答&#xff1a;省級。主管單位&#xff1a;北京電子控股有限責任公司 主辦…

AI安全入門-人工智能數據與模型安全

參考 人工智能數據與模型安全 from 復旦大學視覺與學習實驗室 文章目錄 0. 計算機安全學術知名公眾號1. 概述數據安全模型安全 3. 人工智能安全基礎3.1 基本概念攻擊者攻擊方法受害者受害數據受害模型防御者防御方法威脅模型目標數據替代數據替代模型 3.2 威脅模型3.2.1 白盒威…

實踐致知第16享:設置Word中某一頁橫著的效果及操作

一、背景需求 小姑電話說&#xff1a;現在有個word文檔,里面有個表格太長&#xff08;如下圖所示&#xff09;&#xff0c;希望這一個設置成橫的&#xff0c;其余頁還是保持豎的&#xff01; 二、解決方案 1、將鼠標放置在該頁的最前面閃爍&#xff0c;然后選擇“頁面”》“↘…

Python面經

文章目錄 Python基本概念1. Python是**解釋型**語言還是**編譯型**語言2. Python是**面向對象**語言還是面向過程語言3. Python基本數據類型4.append和 extend區別5.del、pop和remove區別6. sort和sorted區別介紹一下Python 中的字符串編碼is 和 的區別*arg 和**kwarg作用淺拷…