最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器

 更新時(shí)間:2024年08月29日 11:31:58   作者:吃我一個(gè)平底鍋  
本文主要介紹了Go語言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

實(shí)現(xiàn)功能

  • 每個(gè)客戶端上線,服務(wù)端可以向其他客戶端廣播上線信息;
  • 發(fā)送的消息可以廣播給其他在線的客戶
  • 支持改名
  • 支持客戶端主動(dòng)退出
  • 支持通過who查找當(dāng)前在線的用戶
  • 超時(shí)退出

流程

在這里插入圖片描述

變量

  • 用戶結(jié)構(gòu)體 保存用戶的管道,用戶名以及網(wǎng)絡(luò)地址信息
type Client struct {
	C    chan string //用于發(fā)送數(shù)據(jù)的管道
	Name string      //用戶名
	Addr string      //網(wǎng)絡(luò)地址
}
  • 保存在線用戶的map表
var onlineMap map[string]Client
  • 消息通道
var message = make(chan string)

主協(xié)程

  • 監(jiān)聽客戶端的連接請(qǐng)求listener, err := net.Listen("tcp", "127.0.0.1:8000")
  • 當(dāng)客戶端有消息發(fā)送,就向當(dāng)前用戶列表中所有在線用戶轉(zhuǎn)發(fā)消息go Manager()
  • 接受客戶端的請(qǐng)求conn, err1 := listener.Accept()
  • 處理用戶連接go HandleConn(conn)
func main() {
	//監(jiān)聽
	listener, err := net.Listen("tcp", "127.0.0.1:8000")
	if err != nil {
		fmt.Println("net.Listen.err=", err)
		return
	}

	defer listener.Close()

	//新開一個(gè)協(xié)程,轉(zhuǎn)發(fā)消息,只要有消息,就遍歷map,給每個(gè)成員發(fā)送消息
	go Manager()
	//主協(xié)程,循環(huán)阻塞等待用戶連接
	for {
		conn, err1 := listener.Accept()
		if err1 != nil {
			fmt.Println("listener.Accept.err1=", err1)
			continue
		}

		//處理用戶連接
		go HandleConn(conn)
	}

}

處理用戶連接子協(xié)程

  • 獲取客戶端的網(wǎng)絡(luò)地址cliAddr := conn.RemoteAddr().String()
  • 創(chuàng)建一個(gè)用戶結(jié)構(gòu)體,默認(rèn):用戶名和網(wǎng)絡(luò)地址一樣cli := Client{make(chan string), cliAddr, cliAddr},加入map表
  • 給客戶端發(fā)送信息go WriteMsgToClient(cli, conn)
  • 廣播某個(gè)人在線message <- MakeMsg(cli, "login")
  • 提示當(dāng)前用戶 cli.C <- MakeMsg(cli, "I am here")
  • 判斷用戶狀態(tài)isQuit hasData
  • 接收用戶的請(qǐng)求,查看當(dāng)前用戶who,改名rename,發(fā)送消息message
func HandleConn(conn net.Conn) {
	cliAddr := conn.RemoteAddr().String()
	cli := Client{make(chan string), cliAddr, cliAddr}

	//把結(jié)構(gòu)體添加到map
	onlineMap[cliAddr] = cli

	//新開一個(gè)協(xié)程,給客戶端發(fā)送信息
	go WriteMsgToClient(cli, conn)

	//廣播某個(gè)人在線
	message <- MakeMsg(cli, "login")
	//提示當(dāng)前用戶
	cli.C <- MakeMsg(cli, "I am here")

	isQuit := make(chan bool) //對(duì)方是否主動(dòng)退出

	hasData := make(chan bool) //對(duì)方是否有數(shù)據(jù)

	//新開一個(gè)協(xié)程,接收用戶的請(qǐng)求
	go func() {
		buf := make([]byte, 2048)
		for {
			n, err := conn.Read(buf)
			if n == 0 {
				//對(duì)方斷開或者出問題
				isQuit <- true
				fmt.Println("conn.Read.err=", err)
				return
			}
			msg := string(buf[:n-1])
			if len(msg) == 3 && msg == "who" {
				//遍歷map,給當(dāng)前用戶發(fā)送所有成員
				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 = name
				onlineMap[cliAddr] = cli
				conn.Write([]byte("rename ok\n"))

			} else {
				message <- MakeMsg(cli, msg)
			}

			hasData <- true //代表有數(shù)據(jù)

		}

	}()
	for {
		//通過select檢測(cè)channel的流動(dòng)
		select {
		case <-isQuit:
			delete(onlineMap, cliAddr)           //當(dāng)前用戶從map移除
			message <- MakeMsg(cli, "login out") //廣播誰下線了
			return
		case <-hasData:
		case <-time.After(60 * time.Second):
			delete(onlineMap, cliAddr)
			message <- MakeMsg(cli, "time out leave out")
			return
		}
	}

}

給客戶端發(fā)送信息

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

	}

}

發(fā)送消息

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

轉(zhuǎn)發(fā)消息子協(xié)程

有消息到來就進(jìn)行廣播

  • 給map分配空間onlineMap = make(map[string]Client)
  • 遍歷在線用戶列表,轉(zhuǎn)發(fā)消息;沒有消息之前message通道會(huì)阻塞
func Manager() {
	//給map分配空間
	onlineMap = make(map[string]Client)

	for {
		msg := <-message //沒有消息前,會(huì)阻塞
		for _, cli := range onlineMap {
			cli.C <- msg
		}
	}
}

設(shè)計(jì)到的知識(shí)點(diǎn)

  • 網(wǎng)絡(luò)編程,監(jiān)聽客戶端連接,處理連接請(qǐng)求,發(fā)送轉(zhuǎn)發(fā)消息等
  • map,切片,結(jié)構(gòu)體數(shù)據(jù),通道.
  • 通過select檢測(cè)channel的流動(dòng)
  • 并發(fā)編程,開辟子協(xié)程處理當(dāng)前請(qǐng)求等
  • 超時(shí)判斷

效果展示

在這里插入圖片描述

到此這篇關(guān)于Go語言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器的文章就介紹到這了,更多相關(guān)Go語言 廣播式并發(fā)聊天 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • go語言中的udp協(xié)議及TCP通訊實(shí)現(xiàn)示例

    go語言中的udp協(xié)議及TCP通訊實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了go語言中的udp協(xié)議及TCP通訊的實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • Golang中json和jsoniter的區(qū)別使用示例

    Golang中json和jsoniter的區(qū)別使用示例

    這篇文章主要介紹了Golang中json和jsoniter的區(qū)別使用示例,本文給大家分享兩種區(qū)別,結(jié)合示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2023-12-12
  • Go語言kylin任務(wù)自動(dòng)化實(shí)例詳解

    Go語言kylin任務(wù)自動(dòng)化實(shí)例詳解

    這篇文章主要為大家介紹了Go語言kylin任務(wù)自動(dòng)化實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Golang服務(wù)的請(qǐng)求調(diào)度的實(shí)現(xiàn)

    Golang服務(wù)的請(qǐng)求調(diào)度的實(shí)現(xiàn)

    Golang服務(wù)請(qǐng)求調(diào)度是一種使用Go語言實(shí)現(xiàn)的服務(wù)請(qǐng)求管理方法,本文主要介紹了Golang服務(wù)的請(qǐng)求調(diào)度的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-08-08
  • Go并發(fā)編程中sync/errGroup的使用

    Go并發(fā)編程中sync/errGroup的使用

    本文主要介紹了Go并發(fā)編程中sync/errGroup的使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • go?micro微服務(wù)框架項(xiàng)目搭建方法

    go?micro微服務(wù)框架項(xiàng)目搭建方法

    這篇文章主要為大家介紹了go?micro微服務(wù)框架項(xiàng)目搭建方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Golang 協(xié)程配合管道的實(shí)現(xiàn)示例

    Golang 協(xié)程配合管道的實(shí)現(xiàn)示例

    本文主要介紹了Golang協(xié)程配合管道的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01
  • go語言中if語句用法實(shí)例

    go語言中if語句用法實(shí)例

    這篇文章主要介紹了go語言中if語句用法,以實(shí)例形式分析了if語句的定義及使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Go語言常見錯(cuò)誤之將接口定義在實(shí)現(xiàn)方

    Go語言常見錯(cuò)誤之將接口定義在實(shí)現(xiàn)方

    在Go中,接口起到一個(gè)十分關(guān)鍵的角色,它們提供了一種方式來定義對(duì)象的行為,而不需要知道對(duì)象的具體實(shí)現(xiàn),一個(gè)常見的錯(cuò)誤是在實(shí)現(xiàn)方而不是使用方定義接口,本文將詳細(xì)探討為何這樣做是一個(gè)錯(cuò)誤,以及如何避免它
    2024-01-01
  • go實(shí)現(xiàn)自動(dòng)復(fù)制U盤小工具demo

    go實(shí)現(xiàn)自動(dòng)復(fù)制U盤小工具demo

    這篇文章主要為大家介紹了go實(shí)現(xiàn)自動(dòng)復(fù)制U盤小工具demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12

最新評(píng)論

文昌市| 宜春市| 苍山县| 岱山县| 泾川县| 元江| 桑日县| 芦溪县| 罗源县| 凤凰县| 武功县| 湄潭县| 清新县| 禄劝| 西城区| 南和县| 辽阳县| 承德市| 乌海市| 马公市| 清镇市| 梅州市| 张家川| 山丹县| 遂川县| 阿荣旗| 彭山县| 池州市| 两当县| 临颍县| 郎溪县| 武功县| 宝山区| 阳谷县| 宁德市| 东乌珠穆沁旗| 金塔县| 湖北省| 东乡族自治县| 乐至县| 抚顺县|