Go语言实现一个简单的并发聊天室的项目实战

 更新时间:2022年03月18日 16:06:24   作者:Sirius_7  
本文主要介绍了Go语言实现一个简单的并发聊天室的项目实战,文中根据实例编码详细介绍的十分详尽,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

写在前面

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语言 并发聊天室内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • 详解如何在Go中实现优雅停止

    详解如何在Go中实现优雅停止

    和其他语言相比,Go 中有相同也有不同,相同的是实现思路上和其他语言没啥差异,不同在于 Go 采用的是 goroutine + channel 的并发模型,与传统的进程线程相比,实现细节上存在差异,本文将从实际场景和它的一般实现方式展开,逐步讨论这个话题,需要的朋友可以参考下
    2024-04-04
  • Go中的new()和make()函数区别及底层原理详解

    Go中的new()和make()函数区别及底层原理详解

    这篇文章主要为大家介绍了Go中的new()和make()函数区别及底层原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 一文详解Golang中consul的基本使用

    一文详解Golang中consul的基本使用

    consul是一个开源服务注册和服务发现的中心,可以用于微服务的注册和服务之间的调用的发现,帮助上游服务找到下游服务的具体ip:port或者是domain,也可以使用dns的方式让consul帮你去做转发。本文就来讲讲它的具体使用吧
    2023-03-03
  • Golang Socket Server自定义协议的简单实现方案

    Golang Socket Server自定义协议的简单实现方案

    这篇文章主要介绍了Golang Socket Server自定义协议的简单实现方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go语言JSON编解码神器之marshal的运用

    Go语言JSON编解码神器之marshal的运用

    这篇文章主要为大家详细介绍了Go语言中JSON编解码神器——marshal的运用,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-09-09
  • go micro集成链路跟踪的方法和中间件原理解析

    go micro集成链路跟踪的方法和中间件原理解析

    这篇文章主要介绍了go-micro集成链路跟踪的方法和中间件原理,关于Http或者说是Restful服务的链路跟踪,go-micro的httpClient支持CallWrapper,可以用WrapCall来添加链路跟踪的CallWrapper,本文给大家介绍的非常详细,需要的朋友参考下吧
    2022-05-05
  • Golang中map数据类型的使用方法

    Golang中map数据类型的使用方法

    这篇文章主要介绍了Golang中map数据类型的使用方法,文章围绕主题展开详细的内容戒杀,具有一定的参考价值,需要的朋友可以参考一下
    2022-09-09
  • Golang 如何判断数组某个元素是否存在 (isset)

    Golang 如何判断数组某个元素是否存在 (isset)

    这篇文章主要介绍了Golang 如何判断数组某个元素是否存在 (isset),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • go语言的四数相加等于指定数算法

    go语言的四数相加等于指定数算法

    这篇文章主要介绍了go语言的四数相加等于指定数算法的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Golang实现基于Redis的可靠延迟队列

    Golang实现基于Redis的可靠延迟队列

    redisson delayqueue可以使用redis的有序集合结构实现延时队列,遗憾的是go语言社区中并无类似的库。不过问题不大,本文将用Go语言实现这一功能,需要的可以参考一下
    2022-06-06

最新评论