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 相关文章推荐
golang 实现两个结构体复制字段
Apr 28 Golang
彻底理解golang中什么是nil
Apr 29 Golang
go语言使用Casbin实现角色的权限控制
Jun 26 Golang
Golang 语言控制并发 Goroutine的方法
Jun 30 Golang
试了下Golang实现try catch的方法
Jul 01 Golang
入门学习Go的基本语法
Jul 07 Golang
golang内置函数len的小技巧
Jul 25 Golang
Go语言实现Base64、Base58编码与解码
Jul 26 Golang
详解Go语言中Get/Post请求测试
Jun 01 Golang
GoFrame框架数据校验之校验结果Error接口对象
Jun 21 Golang
go goth封装第三方认证库示例详解
Aug 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
第六节--访问属性和方法
2006/11/16 PHP
php下实现折线图效果的代码
2007/04/28 PHP
PHP中$GLOBALS与global的区别详解
2019/03/21 PHP
JavaScript 学习笔记二 字符串拼接
2010/03/28 Javascript
jQuery 下拉列表 二级联动插件分享
2012/03/29 Javascript
jQuery动画效果animate和scrollTop结合使用实例
2014/04/02 Javascript
JQuery选择器绑定事件及修改内容的方法
2015/01/23 Javascript
11种ASP连接数据库的方法
2015/09/18 Javascript
jquery动态添加文本并获取值的方法
2016/10/12 Javascript
jQuery双向列表选择器DIV模拟版
2016/11/01 Javascript
详解React 在服务端渲染的实现
2017/11/16 Javascript
Angular实现双向折叠列表组件的示例代码
2017/11/21 Javascript
微信小程序使用slider设置数据值及switch开关组件功能【附源码下载】
2017/12/09 Javascript
使用watch监听路由变化和watch监听对象的实例
2018/02/24 Javascript
Vue 重置组件到初始状态的方法示例
2018/10/10 Javascript
微信小程序时间控件picker view使用详解
2018/12/28 Javascript
Vue实现商品详情页的评价列表功能
2019/09/04 Javascript
微信小程序实现简单文字跑马灯
2020/05/26 Javascript
python中lambda()的用法
2017/11/16 Python
python使用webdriver爬取微信公众号
2018/08/31 Python
Python中的函数式编程:不可变的数据结构
2018/10/08 Python
Python 实现顺序高斯消元法示例
2019/12/09 Python
python 子类调用父类的构造函数实例
2020/03/12 Python
Python爬虫小例子——爬取51job发布的工作职位
2020/07/10 Python
详解win10下pytorch-gpu安装以及CUDA详细安装过程
2021/01/28 Python
日本网路线上商品代购服务:转送JAPAN
2016/08/05 全球购物
意大利中国电子产品购物网站:Geekmall.com
2019/09/30 全球购物
数据库连接池的工作原理
2012/09/26 面试题
关键字final的用法
2013/10/02 面试题
会计实习期自我鉴定
2013/10/06 职场文书
三八妇女节活动主持词
2014/03/17 职场文书
好习惯伴我成长演讲稿
2014/05/21 职场文书
2014年妇委会工作总结
2014/12/10 职场文书
实习计划书范文
2015/01/16 职场文书
道歉情书大全
2015/05/12 职场文书
消防安全培训工作总结
2015/10/23 职场文书