这段代码实现了一个简单的基于 TCP 的网络聊天室服务器。以下是代码的简述:
代码功能
-
服务器启动:
-
服务器监听
0.0.0.0:8080
端口,等待客户端连接。 -
如果启动失败,会打印错误信息并退出。
-
-
客户端连接处理:
-
每当有客户端连接时,服务器会启动一个独立的协程(
go handleClient(conn)
)来处理该客户端。 -
客户端连接后,服务器提示用户输入网名,并将该客户端的连接存储到
clients
映射中(以网名为键)。
-
-
消息广播:
-
当客户端发送消息时,服务器会调用
broadcastMessage
函数,将消息广播给所有其他客户端。 -
如果客户端断开连接,服务器会从
clients
映射中移除该客户端,并广播离开消息。
-
-
线程安全:
-
使用
sync.Mutex
保护共享资源clients
映射,确保并发访问时的线程安全。
-
代码结构
-
全局变量:
-
clients
:存储客户端连接的映射(map[string]net.Conn
),键为网名,值为客户端连接。 -
mu
:互斥锁,用于保护clients
映射。
-
-
函数:
-
handleClient(conn net.Conn)
:处理客户端连接,读取消息并广播。 -
broadcastMessage(message string)
:将消息广播给所有客户端。 -
main()
:启动服务器,监听客户端连接。
-
代码运行流程
-
启动服务器:
go复制
listener, err := net.Listen("tcp", "0.0.0.0:8080")
-
监听
0.0.0.0:8080
端口。 -
如果监听失败,打印错误信息并退出。
-
-
接受客户端连接:
go复制
for { conn, err := listener.Accept() if err != nil { fmt.Println("Error accepting connection:", err) continue } go handleClient(conn) }
-
循环接受客户端连接。
-
每次接受到连接后,启动一个协程处理该客户端。
-
-
处理客户端连接:
go复制
func handleClient(conn net.Conn) { defer conn.Close() reader := bufio.NewReader(conn) fmt.Fprintf(conn, "请输入您的网名: ") nickname, _ := reader.ReadString('\n') nickname = strings.TrimSpace(nickname) mu.Lock() clients[nickname] = conn mu.Unlock() broadcastMessage(fmt.Sprintf("%s 加入了聊天室\n", nickname)) for { message, err := reader.ReadString('\n') if err != nil { mu.Lock() delete(clients, nickname) mu.Unlock() broadcastMessage(fmt.Sprintf("%s 离开了聊天室\n", nickname)) return } broadcastMessage(fmt.Sprintf("%s: %s", nickname, message)) } }
-
提示客户端输入网名。
-
将客户端连接存储到
clients
映射中。 -
广播新用户加入的消息。
-
循环读取客户端发送的消息,并广播给所有其他客户端。
-
如果客户端断开连接,移除该客户端并广播离开消息。
-
-
广播消息:
go复制
func broadcastMessage(message string) { mu.Lock() defer mu.Unlock() for _, conn := range clients { filteredMessage := strings.Map(func(r rune) rune { if r <= 127 { return r } return -1 }, message) _, err := conn.Write([]byte(filteredMessage)) if err != nil { fmt.Printf("Error broadcasting message: %v\n", err) } } }
-
遍历
clients
映射,将消息发送给每个客户端。 -
使用
strings.Map
过滤消息中的非 ASCII 字符,避免编码问题。
-
总结
这段代码实现了一个简单的 TCP 聊天室服务器,支持多个客户端连接、消息广播和线程安全。每个客户端连接都在独立的协程中处理,服务器通过 sync.Mutex
保护共享资源,确保并发访问的安全性。
复制
再试一次
分享
服务器如何处理多个客户端连接?
客户端断开连接后,服务器如何通知其他用户