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 空map和未初始化map的注意事项说明
Apr 29 Golang
Go语言 go程释放操作(退出/销毁)
Apr 30 Golang
golang 实现时间戳和时间的转化
May 07 Golang
聊聊golang中多个defer的执行顺序
May 08 Golang
go goroutine 怎样进行错误处理
Jul 16 Golang
修改并编译golang源码的操作步骤
Jul 25 Golang
golang内置函数len的小技巧
Jul 25 Golang
使用GO语言实现Mysql数据库CURD的简单示例
Aug 07 Golang
详解Golang如何优雅的终止一个服务
Mar 21 Golang
Go 中的空白标识符下划线
Mar 25 Golang
Golang解析JSON对象
Apr 30 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连接Access数据库的注意事项
2016/08/12 PHP
PHP children()函数讲解
2019/02/03 PHP
phpstudy2020搭建站点的实现示例
2020/10/30 PHP
js实现在文本框光标处添加字符的方法介绍
2012/11/24 Javascript
js中方法重载如何实现?以及函数的参数问题
2013/08/01 Javascript
js简单实现交换Li的值
2014/05/22 Javascript
Javascript中的异步编程规范Promises/A详细介绍
2014/06/06 Javascript
JS+CSS实现可拖拽的漂亮圆角特效弹出层完整实例
2015/02/13 Javascript
使用AmplifyJS组件配合JavaScript进行编程的指南
2015/07/28 Javascript
js验证框架之RealyEasy验证详解
2016/06/08 Javascript
JavaScript数据类型学习笔记分享
2016/09/01 Javascript
jQuery实现导航滚动到指定内容效果完整实例【附demo源码下载】
2016/09/20 Javascript
自制微信公众号一键排版工具
2016/09/22 Javascript
JavaScript数据结构之二叉树的删除算法示例
2017/04/13 Javascript
Vue 实例事件简单示例
2019/09/19 Javascript
Handtrack.js库实现实时监测手部运动(推荐)
2021/02/08 Javascript
[06:30]DOTA2英雄梦之声_第15期_死亡先知
2014/06/21 DOTA
设计模式中的原型模式在Python程序中的应用示例
2016/03/02 Python
关于python下cv.waitKey无响应的原因及解决方法
2019/01/10 Python
浅谈pandas筛选出表中满足另一个表所有条件的数据方法
2019/02/08 Python
分析经典Python开发工程师面试题
2019/04/08 Python
keras实现多GPU或指定GPU的使用介绍
2020/06/17 Python
Python sqlalchemy时间戳及密码管理实现代码详解
2020/08/01 Python
Python headers请求头如何实现快速添加
2020/11/03 Python
使用简单的CSS3属性实现炫酷读者墙效果
2014/01/08 HTML / CSS
La Senza官网:北美顶尖性感内衣品牌
2018/08/03 全球购物
个人找工作自荐信格式
2013/09/21 职场文书
保险专业大专生求职信
2013/10/26 职场文书
公司部门司机岗位职责
2014/01/03 职场文书
竞选部门副经理的自荐书范文
2014/02/11 职场文书
祖国在我心中演讲稿200字
2014/08/28 职场文书
民政局标准版离婚协议书
2014/12/01 职场文书
2015年班级工作总结范文
2015/04/03 职场文书
搭讪开场白台词大全
2015/05/28 职场文书
图解上海144收音机
2021/04/22 无线电
一篇文章告诉你如何实现Vue前端分页和后端分页
2022/02/18 Vue.js