package main

import (   "net"   "fmt"   "strings"   "time")

type Client struct {   C chan string //用户发送数据的通道   Name string //用户名   Addr string //网络地址}

//保存在线用户 cliaddr ======> clientvar onlineMap map[string]Client

var message = make(chan string)

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 + ": login"   return}

func HandleConn(conn net.Conn)  { //处理用户连接   defer conn.Close()   //获取客户端的网络地址   cliAddr := conn.RemoteAddr().String()   //创建一个结构体   cli := Client{make(chan string), cliAddr, cliAddr}   //把结构体添加到map   onlineMap[cliAddr] = cli

   //新开一个协程,专门给当前客户端发送信息   go WriteMsgToClient(cli, conn)

   //广播某个人在线   message <- MakeMsg(cli, "login")

   //提示,我是谁   cli.C <- MakeMsg(cli, "I am here")

   var isQuit = make(chan bool)

   hasData := make(chan bool)

   go func() {      buf := make([]byte, 2048)      for true {         n, err := conn.Read(buf)         if n == 0 { //对方断开,或者出问题            isQuit <- true            fmt.Println("conn.read err = ", err)            return         }         msg := string(buf[:n-1])         if len(msg) == 3 && msg == "who" {            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" {            //rename|mike            name := strings.Split(msg,"|")[1]            cli.Name = name            onlineMap[cliAddr] = cli            conn.Write([]byte("user list :\n"))         }else {            message <- MakeMsg(cli, msg)         }      }   }()

   for true {      select {      case <- isQuit:         delete(onlineMap, cliAddr) //当前用户从map移除         message <- MakeMsg(cli, "log out") //广播谁下线了         return      case <- hasData:         //不做操作      case time.After(60*time.Second): //60秒都没有操作了,超时         delete(onlineMap, cliAddr) //当前用户从map移除         message <- MakeMsg(cli, "tiem out") //广播谁下线了         return       }   }}

func Manager()  {   //给map分配空间map   onlineMap = make(map[string]Client)

   for true {      msg := <-message //没有消息前,这里会阻塞      //遍历map,给map每个成员都发送此消息      for _, cli := range onlineMap{         cli.C <- msg      }   }

}

func main() {   //创建监听   listener, err := net.Listen("tcp", ":8000")   if err != nil {      fmt.Println("net.Listen err = ", err)      return   }

   //新开一个协程,用于转发消息,只要有消息到达 ,那就遍历map然后给map每个成员都发送消息   go Manager()

   //主协程,循环阻塞等待用户连接   for true {      conn, err := listener.Accept()      if err != nil {         fmt.Println("listener.Accept err = ", err)         continue //如果这个不发,説不定还有下个发呢      }      //处理用户的连接      go HandleConn(conn)   }}

执行的结果,当有任何一个新用户登录了,其他所有的用户都会收到登录提醒,这里以ip加端口号的试做为一个唯一标识

转载于:https://www.cnblogs.com/baylorqu/p/9687326.html

[GO]并发实现聊天室服务器相关推荐

  1. java c s聊天程序_Java建立C/S 模式聊天室服务器和客户端

    时间:2018-12-01 概述:聊天室 服务器 客户端 在网络上经常进各种聊天室,本例通过编程实现了C/S 模式的聊天室服务器和客户端.实现方法:ChatServer 类实现了一个聊天室服务器端, ...

  2. Go 快速起步:创建 WebSocket 服务器(聊天室)

    先了解 WebSocket 协议 和 HTTP 协议一样,WebSocket  协议也建立在 TCP/IP 协议基础上,但不一样的是 HTTP 协议 为单向协议,即只能客户端向服务器请求资源,服务器才 ...

  3. 【通信协议及编码】实验3:MFC框架下聊天室客户机与服务器程序

    文章目录 一.实验目的 二.实验环境 三.实验内容 一.实验目的 掌握MFC套接字编程方法 借助VS2016的MFC应用程序向导创建程序框架: 从CSocket类派生用户自定义的套接字类: 通过CAr ...

  4. 基于Python Tkiner、thread与socket实现的简单多人聊天室,在Python中创建TCP服务器与客户端进行通信

    基于Python Tkiner.thread与socket实现的简单多人聊天室,在Python中创建TCP服务器与客户端进行通信 完整代码下载地址:基于Python Tkiner.thread与soc ...

  5. 聊天室---------数据库、部署服务器篇

    数据库 在写聊天室的时候,会经常用到关于数据库的操作,一不小心就会出错,给大家盘点一些易踩坑点 操作数据库段错误 查询出的数据异常 怎么判断查询数据为不存在 数据未加入表 操作数据库段错误 起初对数据 ...

  6. 计算机html大作业聊天室,java大作业设计报告-JAVA聊天室.docx

    PAGE \* MERGEFORMAT18 JAVA程序设计 多人聊天室 设计目的 Java 编程语言是个简单.面向对象.分布式.解释性.健壮.安全与系统无关.可移植.高性能.多线程和静态的语言.本次 ...

  7. 基于TCP网络通信的聊天室

    在实训中,利用简单的ETCP网络通信模式来扩展的聊天室,包括服务器启动关闭.登录.注册.聊天群发以及下线(带音效)等功能,还有连接了数据库JDBC的功能,同时对所有的界面进行美化,在登录,注册界面背景 ...

  8. 比心聊天室的架构演进

    一.比心语音房技术基本介绍 作为一家泛娱乐公司,语音业务是比心最重要的业务之一,而其中最核心的场景就是基于语音房技术实现的聊天室产品.相比于一般的业务系统,语音房业务系统的技术难度会更高一些,其难点主 ...

  9. 架构集二---如何从中台角度搭建直播聊天室

    前言 视频直播已经是一种成熟的产品形态,在不同行业中有多种应用场景.在泛娱乐行业,游戏直播.秀场直播.演唱会直播等已经走进广大用户的日常生活:在电商行业,网红带货直播已经成为增长的新动能:在教育行业, ...

  10. 【Linux网络编程】基于UDP实现多人聊天室

    文章目录 一.UDP的概念 1.1 UDP 1.2 UDP特点 二. 采用UDP实现多人聊天室原因 三.多人聊天室项目功能 四.实现多人聊天室项目流程分析 4.1 前期准备 4.1.1 定义结构体 4 ...

最新文章

  1. Are you missing a call to unregisterReceiver()?
  2. 全面深度复盘:2020北京智源大会文集开放下载(1200页)
  3. GitHub年度报告:Python首次击败Java,中国成第二大开源贡献国
  4. python中文件读写位置的作用-文件操作,读,写,指定位置
  5. PHP CGI 中 fix_pathinfo 引起的安全隐患
  6. 006_FastDFS文件上传
  7. android internet参数传递
  8. HHT变换基本理论-学习笔记
  9. 使用IAM保护您的AWS基础架构
  10. minus出错matlab,请求帮忙指点MATLAB中的语法错误
  11. 研究生,怎么经济独立?
  12. Latex的使用模板
  13. 竣达技术丨24路电压电流采集模块
  14. 计算机网络-自顶向下方法 第五章课后习题答案(第七版)
  15. HW-LCD-070 7寸液晶屏 数据手册
  16. iPhone加码“独立王国” 有可能成摆设?
  17. 如何在patform中加入自己的工程
  18. W7系统dns辅服务器异常,win7dns服务器异常原因及解决方法
  19. 你有你的计划,世界另有计划这本书 万维钢
  20. gets和fgets函数及其区别,C语言gets和fgets函数详解

热门文章

  1. 苹果手机速度慢_安卓手机用户也想体验一下MagSafe充电器?还是算了吧!
  2. 1.3使用command-line runners
  3. Prototype使用$R()函数
  4. 【sklearn第二十六讲】模型评价
  5. Django - 补充目录
  6. linux之awk命令获取最后一列
  7. Css/Js推荐类库
  8. 【转】彻底删除打印机
  9. [算法模板]高斯消元
  10. js事件(事件冒泡与事件捕获)