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 24 Golang
Go语言使用select{}阻塞main函数介绍
Apr 25 Golang
golang 如何用反射reflect操作结构体
Apr 28 Golang
对Golang中的FORM相关字段理解
May 02 Golang
Golang全局变量加锁的问题解决
May 08 Golang
go 实现简易端口扫描的示例
May 22 Golang
使用GO语言实现Mysql数据库CURD的简单示例
Aug 07 Golang
Go语言并发编程 sync.Once
Oct 16 Golang
golang连接MySQl使用sqlx库
Apr 14 Golang
golang语言指针操作
Apr 14 Golang
Golang 并发编程 SingleFlight模式
Apr 26 Golang
Go结合Gin导出Mysql数据到Excel表格
Aug 05 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中批量替换文件名的实现代码
2011/07/20 PHP
PHP获得数组交集与差集的方法
2015/06/10 PHP
PHP抓取淘宝商品的用户晒单评论+图片+搜索商品列表实例
2016/04/14 PHP
Javascript实现的分页函数
2006/12/22 Javascript
js event事件的传递与冒泡处理
2009/12/06 Javascript
JavaScript.Encode手动解码技巧
2010/07/14 Javascript
jquery中ajax学习笔记一
2011/10/16 Javascript
js菜单点击显示或隐藏效果的简单实例
2014/01/13 Javascript
Javascript中的方法链(Method Chaining)介绍
2015/03/15 Javascript
JavaScript动态修改网页元素内容的方法
2015/03/21 Javascript
jquery实现表单验证简单实例演示
2015/11/23 Javascript
javascript事件处理模型实例说明
2016/05/31 Javascript
深入理解ECMAScript的几个关键语句
2016/06/01 Javascript
JQuery validate 验证一个单独的表单元素实例
2017/02/17 Javascript
vue Render中slots的使用的实例代码
2017/07/19 Javascript
AngularJS实现的根据数量与单价计算总价功能示例
2017/12/26 Javascript
JavaScript实现的反序列化json字符串操作示例
2018/07/18 Javascript
angularjs实现table表格td单元格单击变输入框/可编辑状态示例
2019/02/21 Javascript
[46:27]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#2LGD VS MVP.Phx第一局
2016/03/02 DOTA
python实现根据月份和日期得到星座的方法
2015/03/27 Python
python 采集中文乱码问题的完美解决方法
2016/09/27 Python
python批量识别图片指定区域文字内容
2019/04/30 Python
numpy库与pandas库axis=0,axis= 1轴的用法详解
2019/05/27 Python
Python递归函数特点及原理解析
2020/03/04 Python
浅谈keras2 predict和fit_generator的坑
2020/06/17 Python
详解HTML5 data-* 自定义属性
2018/01/24 HTML / CSS
为世界各地的女性设计和生产时尚服装:ROMWE
2016/09/17 全球购物
Notino瑞典:购买香水和美容产品
2019/07/26 全球购物
思想品德自我鉴定
2013/10/12 职场文书
公司员工的自我评价范例
2013/11/01 职场文书
幼儿园教师个人反思
2014/01/30 职场文书
报关报检委托书
2014/04/08 职场文书
文秘求职信范文
2014/04/10 职场文书
公共场所禁烟倡议书
2014/08/30 职场文书
小学感恩节活动总结
2015/03/24 职场文书
严以律己学习心得体会
2016/01/13 职场文书