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 如何用反射reflect操作结构体
Apr 28 Golang
Go语言中break label与goto label的区别
Apr 28 Golang
彻底理解golang中什么是nil
Apr 29 Golang
Goland使用Go Modules创建/管理项目的操作
May 06 Golang
Go语言并发编程 sync.Once
Oct 16 Golang
Golang中channel的原理解读(推荐)
Oct 16 Golang
victoriaMetrics库布隆过滤器初始化及使用详解
Apr 05 Golang
golang连接MySQl使用sqlx库
Apr 14 Golang
golang生成并解析JSON
Apr 14 Golang
golang定时器
Apr 14 Golang
Go获取两个时区的时间差
Apr 20 Golang
Go gRPC进阶教程gRPC转换HTTP
Jun 16 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之第五天
2006/10/09 PHP
PHP 动态随机生成验证码类代码
2010/04/09 PHP
PHP设置一边执行一边输出结果的代码
2013/09/30 PHP
PHP构造函数与析构函数用法示例
2016/09/28 PHP
PHP实现唤起微信支付功能
2019/02/18 PHP
javascript 获取模态窗口的滚动位置代码
2013/08/06 Javascript
jQuery中change事件用法实例
2014/12/26 Javascript
javascript实现复选框选中属性
2015/03/25 Javascript
JavaScript中setUTCMilliseconds()方法的使用详解
2015/06/12 Javascript
JS遍历对象属性的方法示例
2017/01/10 Javascript
微信小程序 图片边框解决方法
2017/01/16 Javascript
ionic2自定义cordova插件开发以及使用(Android)
2017/06/19 Javascript
JavaScript定时器setTimeout()和setInterval()详解
2017/08/18 Javascript
axios全局请求参数设置,请求及返回拦截器的方法
2018/03/05 Javascript
layui实现图片虚拟路径上传,预览和删除的例子
2019/09/25 Javascript
js 实现watch监听数据变化的代码
2019/10/13 Javascript
Vue3.0中的monorepo管理模式的实现
2019/10/14 Javascript
JavaScript碰撞检测原理及其实现代码
2020/03/12 Javascript
Vue实现input宽度随文字长度自适应操作
2020/07/29 Javascript
[01:09:20]NB vs NAVI Supermajor小组赛A组 BO3 第二场 6.2
2018/06/03 DOTA
python requests 测试代理ip是否生效
2018/07/25 Python
解决Python正则表达式匹配反斜杠''\''问题
2019/07/17 Python
django框架两个使用模板实例
2019/12/11 Python
纯CSS3打造动感漂亮时尚的扇形菜单
2014/03/18 HTML / CSS
英国现代绅士品牌:Hackett
2017/12/17 全球购物
吉列剃须刀美国官网:Gillette美国
2018/07/13 全球购物
新闻学专业应届生求职信
2013/11/08 职场文书
师生聚会感言
2014/01/26 职场文书
给小学生的新年寄语
2014/04/04 职场文书
申论倡议书范文
2014/05/13 职场文书
区域销售主管岗位职责
2014/06/15 职场文书
英语分层教学实施方案
2014/06/15 职场文书
幼儿园感恩节活动方案
2014/10/06 职场文书
因公司原因离职的辞职信范文
2015/05/12 职场文书
小学一年级班主任工作经验交流材料
2015/11/02 职场文书
青年人初次创业的“五不要”
2019/08/23 职场文书