答案是利用Go的goroutine和channel实现并发聊天室,服务器通过net.Listen监听连接,为每个客户端启动goroutine处理读写,使用joinChan、leaveChan和messageChan管理客户端状态与消息广播,客户端则通过独立goroutine分别处理输入输出,确保高效并发通信。

一个简单的Golang聊天室客户端与服务器,其核心在于利用Go语言强大的并发特性,通过
net
说实话,第一次尝试用Go写聊天室,最让我感到惊艳的就是它处理并发的优雅。你不用去操心线程池那些复杂的玩意儿,直接一个
go
服务器端的核心逻辑其实不复杂:
net.Listen
listener.Accept()
map[net.Conn]bool
map[string]net.Conn
sync.Mutex
客户端这边就相对直白一些:
立即学习“go语言免费学习笔记(深入)”;
net.Dial
os.Stdin
conn.Write
conn.Read
这里我通常会设置一个全局的
messageChan
broadcast
messageChan
messageChan
代码示例(Server端骨架):
package main
import (
"bufio"
"fmt"
"log"
"net"
"sync"
"time"
)
// client 结构体代表一个连接到服务器的客户端
type client struct {
conn net.Conn
username string
// incoming 用于接收来自此客户端的消息(由客户端reader goroutine发送)
incoming chan string
// outgoing 用于发送消息给此客户端(由broadcaster goroutine发送)
outgoing chan string
}
var (
// clients 存储所有活跃的客户端,用于广播消息
clients = make(map[*client]bool)
mu sync.Mutex // 保护 clients map 的并发访问
joinChan = make(chan *client) // 新客户端加入的通知通道
leaveChan = make(chan *client) // 客户端离开的通知通道
messageChan = make(chan string) // 所有客户端发送的消息都会汇聚到这里
)
func main() {
listener, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatalf("无法监听端口: %v", err)
}
defer listener.Close()
fmt.Println("聊天室服务器已启动,监听端口: 8080")
go broadcaster() // 启动消息广播器 goroutine
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("接受连接失败: %v", err)
continue
}
go handleConnection(conn) // 为每个新连接启动一个 goroutine 处理
}
}
// handleConnection 处理单个客户端连接
func handleConnection(conn net.Conn) {
defer conn.Close() // 确保连接最终被关闭
// 简单的用户名生成
username := fmt.Sprintf("匿名用户%d", time.Now().UnixNano()%1000)
cli := &client{
conn: conn,
username: username,
incoming: make(chan string),
outgoing: make(chan string),
}
joinChan <- cli // 通知广播器有新客户端加入
// 启动 goroutine 处理客户端的输入和输出
go cli.reader() // 从客户端读取消息
go cli.writer() // 向客户端写入消息
// 阻塞,直到客户端的reader goroutine关闭incoming channel,表示客户端断开
// 这是为了让 handleConnection goroutine 保持活跃,直到客户端真正断开
<-cli.incoming
leaveChan <- cli // 通知广播器有客户端离开
log.Printf("客户端 %s (%s) 已断开连接", cli.username, cli.conn.RemoteAddr())
}
// reader goroutine 负责从客户端连接读取消息
func (c *client) reader() {
scanner := bufio.NewScanner(c.conn)
for scanner.Scan() {
msg := scanner.Text()
messageChan <- fmt.Sprintf("%s: %s", c.username, msg) // 将客户端消息发送到公共消息通道
}
// 如果 scanner.Scan() 返回 false,说明客户端断开或发生错误
close(c.incoming) // 关闭 incoming channel,通知 handleConnection goroutine 客户端已断开
}
// writer goroutine 负责向客户端连接写入消息
func (c *client) writer() {
for msg := range c.outgoing { // 从 outgoing channel 接收消息
_, err := fmt.Fprintln(c.conn, msg)
if err != nil {
log.Printf("发送消息给 %s 失败: %v", c.username, err)
return // 写入失败,关闭 writer以上就是Golang实现简单聊天室客户端与服务器的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号