Go实现简易聊天室(群聊)
参考:Go 群聊 ( goroutine ) · 语雀基于websocket的聊天室,可进一步参考:(1)go实现聊天室(WebSocket方式)(2)Golang代码搜集-基于websocket+vue.js的简易聊天室聊天室的组成聊天室分为两个部分,分别是:服务端客户端然后,一般情况下我们互相聊天使用的都只是客户端而已,服务端只是起到调度的作用。信息发送与接收的流程假设我们有服务端(S)客户端
·
参考:Go 群聊 ( goroutine ) · 语雀
基于websocket的聊天室,可进一步参考:
(1) go实现聊天室(WebSocket方式)
(2) Golang代码搜集-基于websocket+vue.js的简易聊天室
闲着无聊ing~
一直想着能用go整一些好玩的小工具,想着想着突然想到实现一个简易的群聊工具,然后看了上面几个大佬文章,边看边动手实现下...
聊天室的组成
聊天室分为两个部分,分别是:
- 服务端
- 客户端
然后,一般情况下我们互相聊天使用的都只是客户端而已,服务端只是起到调度的作用。
信息发送与接收的流程
假设我们有 服务端(S) 客户端(C1) 客户端(C2) 客户端(C3)并且 S 已经 与 C1 C2 C3 建立了连接。
理论上的流程是这样的:
- C1 向 S 发出信息
- S 接收到信息
- S 将接收到的信息广播给 C2 C3
- C2 C3 接收信息
服务端代码
package main
import (
"fmt"
"net"
"time"
)
// 客户端 map
var clientMap = make(map[string]*net.TCPConn) // 存储当前群聊中所有用户连接信息:key: ip+port, val: 用户连接信息
// 监听请求
func listenClient(ipAndPort string) {
tcpAddr, _ := net.ResolveTCPAddr("tcp", ipAndPort)
tcpListener, _ := net.ListenTCP("tcp", tcpAddr)
for { // 循环接收
clientConn, _ := tcpListener.AcceptTCP() // 监听请求连接
clientMap[clientConn.RemoteAddr().String()] = clientConn // 将连接添加到 map
go addReceiver(clientConn)
fmt.Println("用户 : ", clientConn.RemoteAddr().String(), " 已连接.")
}
}
// 向连接添加接收器
func addReceiver(newConnect *net.TCPConn) {
for {
byteMsg := make([]byte, 2048)
len, err := newConnect.Read(byteMsg) // 从newConnect中读取信息到缓存中
if err != nil {
newConnect.Close()
}
fmt.Println(string(byteMsg[:len]))
msgBroadcast(byteMsg[:len], newConnect.RemoteAddr().String())
}
}
// 广播给所有 client
func msgBroadcast(byteMsg []byte, key string) {
for k, con := range clientMap {
if k != key { // 转发消息给当前群聊中,除自身以外的其他用户
con.Write(byteMsg)
}
}
}
// 初始化
func initGroupChatServer() {
fmt.Println("服务已启动...")
time.Sleep(1 * time.Second)
fmt.Println("等待客户端请求连接...")
go listenClient("127.0.0.1:1801")
select {}
}
func main() {
initGroupChatServer()
}
客户端代码
package main
import (
"bufio"
"fmt"
"net"
"os"
)
// 用户名
var loginName string
// 本机连接
var selfConnect *net.TCPConn
// 读取行文本
var reader = bufio.NewReader(os.Stdin)
// 建立连接
func connect(addr string) {
tcpAddr, _ := net.ResolveTCPAddr("tcp", addr) // 使用tcp
con, err := net.DialTCP("tcp", nil, tcpAddr) // 拨号:主动向server建立连接
selfConnect = con
if err != nil {
fmt.Println("连接服务器失败")
os.Exit(1)
}
go msgSender()
go msgReceiver()
}
// 消息接收器
func msgReceiver() {
buff := make([]byte, 2048)
for {
len, _ := selfConnect.Read(buff) // 从建立连接的缓冲区读消息
fmt.Println(string(buff[:len]))
}
}
// 消息发送器
func msgSender() {
for {
bMsg, _, _ := reader.ReadLine()
bMsg = []byte(loginName + " : " + string(bMsg))
selfConnect.Write(bMsg) // 发消息
}
}
// 初始化
func initGroupChatClient() {
fmt.Println("请问您怎么称呼?")
bName, _, _ := reader.ReadLine()
loginName = string(bName)
connect("127.0.0.1:1801")
select {}
}
func main() {
initGroupChatClient()
}
运行结果展示:
server端:
client端:
更多推荐
已为社区贡献1条内容
所有评论(0)