欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

go消息服务器吗,Go语言聊天服务器

发布时间:2025/3/21 编程问答 28 豆豆
生活随笔 收集整理的这篇文章主要介绍了 go消息服务器吗,Go语言聊天服务器 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

本节将带领大家结合咱们前面所学的知识开发一个聊天的小程序,它可以在几个用户之间相互广播文本消息。这个程序里包含4个goroutine。主goroutine和广播(broadcaster)goroutine,每一个连接里面有一个连接处理(handleConn)goroutine和一个客户写入(clientwriter)goroutine。

广播器(broadcaster)是关于如何使用select的一个规范说明,因为它需要对三种不同的消息进行响应。

如下所示,主goroutine的工作是监听端口,接受连接客户端的网络连接。对每一个连接,它创建一个新的handleConngoroutine。

packagemainimport("bufio""fmt""log""net")funcmain(){listener,err:=net.Listen("tcp","localhost:8000")iferr!=nil{log.Fatal(err)}gobroadcaster()for{conn,err:=listener.Accept()iferr!=nil{log.Print(err)continue}gohandleConn(conn)}}

下一个是广播器,它使用局部变量clients来记录当前连接的客户集合。每个客户唯一被记录的信息是其对外发送消息通道的ID,下面是细节:

typeclientchan

广播者监听两个全局的通道entering和leaving,通过它们通知客户的到来和离开,如果它从其中一个接收到事件,它将更新clients集合。如果客户离开,那么它关闭对应客户对外发送消息的通道。

广播者也监听来自messages通道的事件,所有的客户都将消息发送到这个通道。当广播者接收到其中一个事件时,它把消息广播给所有客户。

现在来看一下每个客户自己的goroutine。handleConn函数创建一个对外发送消息的新通道,然后通过entering通道通知广播者新客户到来。

接着,它读取客户发来的每一行文本,通过全局接收消息通道将每一行发送给广播者,发送时在每条消息前面加上发送者ID作为前缀。一旦从客户端读取完毕消息,handleConn通过leaving通道通知客户离开,然后关闭连接。

funchandleConn(connnet.Conn){ch:=make(chanstring)//对外发送客户消息的通道goclientWriter(conn,ch)who:=conn.RemoteAddr().String()ch

另外,handleConn函数还为每一个客户创建了写入(clientwriter)goroutine,它接收消息,广播到客户的发送消息通道中,然后将它们写到客户的网络连接中。客户写入者的循环在广播者收到leaving通知并且关闭客户的发送消息通道后终止。

下面的信息展示了同一个机器上的一个服务器和两个客户端,它们使用netcat程序来聊天:

$gobuildgopl.io/ch8/main

$gobuildgopl.io/ch8/netcat

$./main&

$./netcat

Youare127.0.0.1:64208  $./netcat

127.0.0.1:64211hasarrivedYouare127.0.0.1:64211

Hi!

127.0.0.1:64208:Hi! 127.0.0.1:64208:Hi!

Hiyourself.

127.0.0.1:64211:Hiyourself. 127.0.0.1:64211:Hiyourself.

^C

127.0.0.1:64208hasleft

$./netcat

Youare127.0.0.1:64216 127.0.0.1:64216hasarrived

Welcome.

127.0.0.1:64211:Welcome.127.0.0.1:64211:Welcome.

^C

127.0.0.1:64211hasleft

netcat的完整代码如下所示:

//netcat.go//netcat是一个简单的TCP服务器读/写客户端packagemainimport("io""log""net""os")funcmain(){conn,err:=net.Dial("tcp","localhost:8000")iferr!=nil{log.Fatal(err)}done:=make(chanstruct{})gofunc(){io.Copy(os.Stdout,conn)//注意:忽略错误log.Println("done")done

当有n个客户session在连接的时候,程序并发运行着2n+2个相互通信的goroutine,它不需要隐式的加锁操作。clientsmap限制在广播器这一个goroutine中被访问,所以不会并发访问它。唯一被多个goroutine共享的变量是通道以及net.Conn的实例,它们又都是并发安全的。

总结

以上是生活随笔为你收集整理的go消息服务器吗,Go语言聊天服务器的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。