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.mzph.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; 从而帮…

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等新型激活函数。深入分析了各类激活函数的数学表达、特点优势、局限性以及在典型模型中的应用情况。通过系统的对比分析,本文探讨了激…

详解MySQL中的递归查询

MySQL中的递归查询主要通过WITH RECURSIVE语句来实现&#xff0c;这在处理具有层级关系或树形结构的数据时非常有用。下面将通过一个具体的例子来详细解释如何在MySQL中使用递归查询。 示例场景 假设我们有一个部门表&#xff08;departments&#xff09;&#xff0c;其中包含…

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

仓储管理系统是什么&#xff1f; 仓储管理系统&#xff08;WMS&#xff09;是一个全面的软件解决方案&#xff0c;旨在帮助企业优化仓库管理流程、管理和控制日常仓库运营。通过数学模型和信息手段&#xff0c;对仓库管理的各个环节进行优化和调控&#xff0c;涵盖了从货物入库…

使用网关和Spring Security进行认证和授权

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

怎么录制视频?电脑录制,试试这3种方法

在数字化快速发展的时代&#xff0c;视频已经成为我们传递信息、分享生活、表达情感的重要载体。每一个人都希望自己能够掌握视频录制技巧&#xff0c;轻松驾驭影像的力量&#xff0c;创造出属于自己的视觉盛宴。 那么&#xff0c;怎么录制视频呢&#xff1f;首先选择一款好用…

《信息与电脑(理论版)》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《信息与电脑(理论版)》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊。 问&#xff1a;《信息与电脑(理论版)》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;北京电子控股有限责任公司 主办…

实践致知第16享:设置Word中某一页横着的效果及操作

一、背景需求 小姑电话说&#xff1a;现在有个word文档,里面有个表格太长&#xff08;如下图所示&#xff09;&#xff0c;希望这一个设置成横的&#xff0c;其余页还是保持竖的&#xff01; 二、解决方案 1、将鼠标放置在该页的最前面闪烁&#xff0c;然后选择“页面”》“↘…

【Stable Diffusion】(基础篇三)—— 图生图基础

图生图基础 本系列笔记主要参考B站nenly同学的视频教程&#xff0c;传送门&#xff1a;B站第一套系统的AI绘画课&#xff01;零基础学会Stable Diffusion&#xff0c;这绝对是你看过的最容易上手的AI绘画教程 | SD WebUI 保姆级攻略_哔哩哔哩_bilibili 本文主要讲解如何使用S…

K8s集群初始化遇到的问题

kubectl describe pod coredns-545d6fc579-s9g5s -n kube-system 找到原因1&#xff1a;CoreDNS Pod 处于 Pending 状态的原因是集群中的节点都带有 node.kubernetes.io/not-ready 污点 journalctl -u kubelet -f 14:57:59.178592 3553 remote_image.go:114] "PullIma…

pear-admin-fast项目修改为集成PostgreSQL启动

全局搜索代码中的sysdate()&#xff0c;修改为now() 【前者是mysql特有的&#xff0c;后者是postgre特有的】修改application-dev.yml中的数据库url使用DBeaver把mysql中的数据库表导出csv&#xff0c;再从postgre中导入csv脚本转换后出现了bpchar(xx)类型&#xff0c;那么一定…

python数据可视化(6)——绘制散点图

课程学习来源&#xff1a;b站up&#xff1a;【蚂蚁学python】 【课程链接&#xff1a;【【数据可视化】Python数据图表可视化入门到实战】】 【课程资料链接&#xff1a;【链接】】 Python绘制散点图查看BMI与保险费的关系 散点图: 用两组数据构成多个坐标点&#xff0c;考察…

如何降低老年人患帕金森病的风险?

降低老年人患帕金森病风险的方法 避免接触有害物质&#xff1a;长期接触某些化学物质、农药或其他有害物质可能会增加患帕金森病的风险。应减少这些物质的暴露&#xff0c;例如在工作或生活中采取防护措施。 健康饮食&#xff1a;均衡饮食&#xff0c;多吃富含抗氧化剂的食物&a…

做了一个万能搜索框

最近给网页做了一个搜索框&#xff0c;现在搜索比以前更加方便了&#xff0c;下面简单介绍一下如何使用 我们进入网页版&#xff08;app.zyjj.cc&#xff09;点击右上角的搜索就可以看到这个新版的搜索框了 目前支持中文、拼音、首字母等多种搜索方式&#xff0c;大家可以随意…

【Linux】常见指令(下)

【Linux】常见指令&#xff08;下&#xff09; 通配符 *man指令cp指令echo指令cat指令&#xff08;简单介绍&#xff09;cp指令 mv指令alias指令which ctrl ccat指令linux下一切皆文件 more指令less指令head指令tail指令管道 通配符 ‘*’ 通配符’ *‘&#xff0c;是可以匹配…

4 C 语言控制流与循环结构的深入解读

目录 1 复杂表达式的计算过程 2 if-else语句 2.1 基本结构及示例 2.2 if-else if 多分支 2.3 嵌套 if-else 2.4 悬空的 else 2.5 注意事项 2.5.1 if 后面不要加分号 2.5.2 省略 else 2.5.3 省略 {} 2.5.4 注意点 3 while 循环 3.1 一般形式 3.2 流程特点 3.3 注…

数电基础 - 可编程逻辑器件

目录 ​编辑 一. 简介 二. 现场可编程逻辑阵列 三. 可编程阵列逻辑 四. 通用阵列逻辑 五. 可擦除的可编程逻辑器件 六. 复杂的可编程逻辑器件 七. 现场可编程门阵列 一. 简介 可编程逻辑器件&#xff08;Programmable Logic Device&#xff0c;PLD&#xff09;是一种用…