Go语言实现一个简单的并发聊天室的项目实战


Posted in Golang onMarch 18, 2022

写在前面

Go语言在很多方面天然的具备很多便捷性,譬如网络编程,并发编程。而通道则又是Go语言实现并发编程的重要工具,因为其承担着通道之间互相通信的重任。并且因为其本身就是并发安全的,所以在某些场景下是非常好用的。

并发聊天服务器

这里主要是实现一个简单的并发聊天服务器。首先,客户端可以在服务器中注册自己的信息(登录以及退出),客户端发出的所有的信息由服务器向各个客户端进行转发,或者换句话说是广播。

具体代码

服务端

说的再多,没有代码简单明了,直接上代码~

package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
)
type client chan <- string //定义一个单向的向外发送数据的通道

var (
    entering = make(chan client)
    leaving = make(chan client)
    messages = make(chan string)
)

func main() {
    listener, err := net.Listen("tcp","localhost:8000")
    if err != nil {
        log.Fatal("network is broken", err)
    }
    go broadcaster()
    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Print(err)
            continue
        }
        go handleConn1(conn)
    }
}
func broadcaster()  {
    clients := make(map[client]bool) //存储每个client的登录状态
    for{
        select {
        case msg := <-messages:
            for cli := range clients {
                cli <- msg
            }
        case cli := <-entering:
            clients[cli] = true
        case cli := <-leaving:
            delete(clients,cli)
            close(cli)
        }
    }
}

func handleConn1(conn net.Conn)  {
    ch := make(chan string)
    go clientWriter(conn, ch)
    who := conn.RemoteAddr().String()
    ch <- "You are " + who
    entering <- ch
    messages <- who + "has arrived"

    input := bufio.NewScanner(conn)
    for input.Scan() {
        messages <- who + ":" + input.Text()
    }

    leaving <- ch
    messages <- who + "has left"
    conn.Close()
}

func clientWriter(conn net.Conn, ch <- chan string)  {
    for msg := range ch {
        fmt.Fprintln(conn, msg)
    }
}

客户端

客户端相对简单,只是涉及到信息的发送和接受工作。

package main

import (
    "io"
    "log"
    "net"
    "os"
)

func main() {
    conn, err := net.Dial("tcp","localhost:8000")
    if err != nil {
        log.Fatal("Connected has been refused!",err)
    }
    defer conn.Close()
    go mesCopy(os.Stdout,conn)
    mesCopy(conn,os.Stdin)
}

func mesCopy(des io.Writer, res io.Reader)  {
    if _, err := io.Copy(des, res); err != nil {
        log.Print("wrong!")
    }
}

 总结

实现原理较为简单,所以代码并没有多少注释,如果有任何疑问,欢迎留言讨论。最后说一句,在MIT的课程中,其实并不是很推荐在并发编程中使用通道chan,除非你对其应用的场景和可能出现的情况有很好的把握,不然可能会出现很多不可预测的事情,譬如死锁(见另外一篇博客)。在这种时候,共享变量将会是一种很好的选择,具体查看go多线程实践。

到此这篇关于Go语言实现一个简单的并发聊天室的项目实战的文章就介绍到这了,更多相关Go语言 并发聊天室内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Golang 相关文章推荐
Go语言操作数据库及其常规操作的示例代码
Apr 21 Golang
Golang 正则匹配效率详解
Apr 25 Golang
Go语言中的UTF-8实现
Apr 26 Golang
golang 实现时间戳和时间的转化
May 07 Golang
Golang全局变量加锁的问题解决
May 08 Golang
GoLang中生成UUID唯一标识的实现
May 08 Golang
go 实现简易端口扫描的示例
May 22 Golang
Go语言实现Snowflake雪花算法
Jun 08 Golang
入门学习Go的基本语法
Jul 07 Golang
基于Go语言构建RESTful API服务
Jul 25 Golang
Go Plugins插件的实现方式
Aug 07 Golang
GO语言异常处理分析 err接口及defer延迟
Apr 14 Golang
浅谈GO中的Channel以及死锁的造成
Mar 18 #Golang
Golang 并发下的问题定位及解决方案
Mar 16 #Golang
如何利用golang运用mysql数据库
深入理解go缓存库freecache的使用
Feb 15 #Golang
Go语言读取txt文档的操作方法
Jan 22 #Golang
一文搞懂Golang 时间和日期相关函数
Go语言基础切片的创建及初始化示例详解
Nov 17 #Golang
You might like
php 提速工具eAccelerator 配置参数详解
2010/05/16 PHP
php 5.3.5安装memcache注意事项小结
2011/04/12 PHP
php中session退出登陆问题
2014/02/27 PHP
php实现读取手机客户端浏览器的类
2015/01/09 PHP
php7 错误处理机制修改实例分析
2020/05/25 PHP
JQuery Dialog(JS 模态窗口,可拖拽的DIV)
2010/02/07 Javascript
jquery获取颜色在ie和ff下的区别示例介绍
2014/03/28 Javascript
JavaScript获取页面上被选中文字的方法技巧
2015/03/13 Javascript
JS+DIV实现鼠标划过切换层效果的方法
2015/05/25 Javascript
JS获取元素多层嵌套思路详解
2016/05/16 Javascript
jQuery学习心得总结(必看篇)
2016/06/10 Javascript
JS跳转手机站url的若干注意事项
2017/10/18 Javascript
Vue按需加载的具体实现
2017/12/02 Javascript
关于Mac下安装nodejs、npm和cnpm的教程
2018/04/11 NodeJs
详解使用create-react-app快速构建React开发环境
2018/05/16 Javascript
Windows系统下安装Python的SSH模块教程
2015/02/05 Python
在Python中使用defaultdict初始化字典以及应用方法
2018/10/31 Python
PyCharm鼠标右键不显示Run unittest的解决方法
2018/11/30 Python
Python爬虫之UserAgent的使用实例
2019/02/21 Python
在PyCharm中控制台输出日志分层级分颜色显示的方法
2019/07/11 Python
解析PyCharm Python运行权限问题
2020/01/08 Python
keras自定义损失函数并且模型加载的写法介绍
2020/06/15 Python
CSS3 实现的火焰动画
2020/12/07 HTML / CSS
HTML5地理定位实例
2014/10/15 HTML / CSS
Regatta官网:英国最受欢迎的户外服装和鞋类品牌
2019/05/01 全球购物
最新英语专业学生求职信范文
2013/09/21 职场文书
海南地接欢迎词
2014/01/14 职场文书
物业保安员岗位职责
2014/03/14 职场文书
优秀护士演讲稿
2014/04/30 职场文书
运动会演讲稿200字
2014/08/25 职场文书
领导干部“四风”查摆问题个人整改措施
2014/10/28 职场文书
会计工作岗位职责
2015/02/03 职场文书
thinkphp 获取控制器及控制器方法
2021/04/16 PHP
python3.9之你应该知道的新特性详解
2021/04/29 Python
JavaScript offset实现鼠标坐标获取和窗口内模块拖动
2021/05/30 Javascript
正则表达式拆分url实例代码
2022/02/24 Java/Android