go_并发聊天室
2019-03-07 21:20
162 查看
版权声明:本文为博主原创文章,转载请附上博文链接! https://blog.csdn.net/weixin_43851310/article/details/88321095
用法:
使用nc工具
win+r打开多个终端,分别在终端输入:nc 127.0.0.1 8080
不同终端之间可以进行简单的通信
介绍:
声明handler函数,进行处理客户端发来的信息
声明broadcaster函数,进行全局广播,传递数据
程序使用了channel进行数据的阻塞和传递
package main import ( "bufio" "fmt" "net" "time" ) type Client struct { Name string Addr string ch chan string } var( entering = make(chan Client) message = make(chan string) leaving = make(chan Client) list = make(chan Client) rename = make(chan Client) ) func broadcaster(){ clients := make(map[string] Client) for { select { case cli := <- entering: clients[cli.Addr] = cli case msg := <- message: for _,cli := range clients { cli.ch <- msg } case cli := <- leaving: delete(clients, cli.Addr) close(cli.ch) case cli := <- list: cli.ch <- "list of users:" for _, v := range clients { cli.ch <- "[" + v.Addr + "]" + v.Name } case cli := <- rename: clients[cli.Addr] = cli } } } //处理客户端发来的信息 func handler(conn net.Conn) { ch := make(chan string) go clientWriter(conn, ch) //客户端连接地址 addr := conn.RemoteAddr().String() name := addr cli := Client{name,addr,ch} //通知客户端自己的名字 ch <- "You are:" + cli.Name //广播给所有在线用户,新的用户链入 message <- cli.Name + "has arrived" entering <- cli //超时强踢功能 hasData := make(chan struct{}) go func() { for { select { case <- hasData: case <- time.After(time.Second * 10): conn.Close() return } } }() //循环读取conn中的消息 input := bufio.NewScanner(conn) for input.Scan(){ msg := input.Text() if msg == "#list" { list <- cli } else if len(msg)>8 && len(msg)<126 && msg[:8]=="#rename|" { cli.Name = msg[8:] rename <- cli } else { message <- cli.Name + "say:" + input.Text() } //重置超时强踢计时 hasData <- struct{}{} } //客户端断开链接是,把客户端信息写入leaving通道,通知broadcaster断开连接 leaving <- cli message <- cli.Name + "has left" conn.Close() } //监听广播者的信息,并把消息写入客户端 func clientWriter(conn net.Conn, ch chan string) { for msg := range ch { fmt.Fprintln(conn,msg) } } func main() { listener, err := net.Listen("tcp","127.0.0.1:8080") if err != nil { fmt.Println("net.Listen err ",err) return } go broadcaster() for { conn, err := listener.Accept() if err != nil { fmt.Println("listener.Accept err ",err) continue } go handler(conn) } }
相关文章推荐
- Golang语言快速上手到综合实战(Go语言、Beego框架、高并发聊天室、豆瓣电影爬虫) 下载
- Golang语言快速上手到综合实战(Go语言、Beego框架、高并发聊天室、豆瓣电影爬虫)
- ngx_lua与go高并发性能对比
- Go语言-并发通信
- GO语言学习-并发
- GO并发
- go读取超大文件内容并发写入到redis的功能
- Go语言并发与并行学习笔记(一)
- Go方法与并发
- Go并发:利用sync.Once延迟加载
- Go -- 并发编程的两种限速方法
- Go语言的并发和并行
- 《Go in action》读后记录:Go的并发与并行
- 第11课 Go并发
- go语言之并发
- Go程序设计3——并发编程
- Go之简单并发
- Go语言并发之美
- Go语言并发机制初探
- go并发学习