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协程池模拟实现群发邮件功能
May 02 Golang
基于Golang 高并发问题的解决方案
May 08 Golang
golang中的并发和并行
May 08 Golang
Golang全局变量加锁的问题解决
May 08 Golang
GoLang中生成UUID唯一标识的实现
May 08 Golang
浅谈Golang 切片(slice)扩容机制的原理
Jun 09 Golang
Go语言并发编程 sync.Once
Oct 16 Golang
golang三种设计模式之简单工厂、方法工厂和抽象工厂
Apr 10 Golang
Go语言grpc和protobuf
Apr 13 Golang
实现GO语言对数组切片去重
Apr 20 Golang
Golang bufio详细讲解
Apr 21 Golang
基于Python实现西西成语接龙小助手
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调用C代码的实现方法
2014/03/11 PHP
PHP批量生成静态HTML的简单原理和方法
2014/04/20 PHP
windows服务器中检测PHP SSL是否开启以及开启SSL的方法
2014/04/25 PHP
PHP获取客户端真实IP地址的5种情况分析和实现代码
2014/07/08 PHP
PHP封装的Twitter访问类实例
2015/07/18 PHP
PHP创建/删除/复制文件夹、文件
2016/05/03 PHP
ThinkPHP框架中使用Memcached缓存数据的方法
2018/03/31 PHP
通过代码实例解析PHP session工作原理
2020/12/11 PHP
利用Javascript判断操作系统的类型实现不同操作系统下的兼容性
2013/01/29 Javascript
Bootstrap打造一个左侧折叠菜单的系统模板(二)
2016/05/17 Javascript
Angularjs中三种数据的绑定策略(“@”,“=”,“&amp;”)
2016/12/23 Javascript
express如何使用session与cookie的方法
2018/01/30 Javascript
layui获取多选框中的值方法
2018/08/15 Javascript
基于vue2.0实现仿百度前端分页效果附实现代码
2018/10/30 Javascript
zepto.js 实时监听输入框的方法
2018/12/04 Javascript
详解Vue 匿名、具名和作用域插槽的使用方法
2019/04/22 Javascript
微信小程序实现form表单本地储存数据
2019/06/27 Javascript
详解Webpack4多页应用打包方案
2020/07/16 Javascript
解决Vue + Echarts 使用markLine标线(precision精度问题)
2020/07/20 Javascript
Python/Django后端使用PIL Image生成头像缩略图
2019/04/30 Python
使用python进行广告点击率的预测的实现
2019/07/04 Python
Django应用程序入口WSGIHandler源码解析
2019/08/05 Python
关于pandas的离散化,面元划分详解
2019/11/22 Python
Python 元组拆包示例(Tuple Unpacking)
2019/12/24 Python
python3+openCV 获取图片中文本区域的最小外接矩形实例
2020/06/02 Python
python批量修改交换机密码的示例
2020/09/22 Python
html5实现canvas阴影效果示例
2014/05/07 HTML / CSS
编程实现当输入某产品代码则打印出该产品记录的功能
2014/05/03 面试题
工业自动化毕业生自荐信范文
2014/01/04 职场文书
领导视察欢迎词
2014/01/15 职场文书
人民教师的自我评价分享
2014/02/21 职场文书
专科应届毕业生求职信
2014/06/04 职场文书
幼儿园大班毕业评语
2014/12/31 职场文书
Html分层的box-shadow效果的示例代码
2021/03/30 HTML / CSS
Python Socket编程详解
2021/04/25 Python
Java完整实现记事本代码
2022/06/16 Java/Android