tcp网络聊天室

这段代码实现了一个简单的基于 TCP 的网络聊天室服务器。以下是代码的简述:

代码功能

  1. 服务器启动

    • 服务器监听 0.0.0.0:8080 端口,等待客户端连接。

    • 如果启动失败,会打印错误信息并退出。

  2. 客户端连接处理

    • 每当有客户端连接时,服务器会启动一个独立的协程(go handleClient(conn))来处理该客户端。

    • 客户端连接后,服务器提示用户输入网名,并将该客户端的连接存储到 clients 映射中(以网名为键)。

  3. 消息广播

    • 当客户端发送消息时,服务器会调用 broadcastMessage 函数,将消息广播给所有其他客户端。

    • 如果客户端断开连接,服务器会从 clients 映射中移除该客户端,并广播离开消息。

  4. 线程安全

    • 使用 sync.Mutex 保护共享资源 clients 映射,确保并发访问时的线程安全。

代码结构

  • 全局变量

    • clients:存储客户端连接的映射(map[string]net.Conn),键为网名,值为客户端连接。

    • mu:互斥锁,用于保护 clients 映射。

  • 函数

    • handleClient(conn net.Conn):处理客户端连接,读取消息并广播。

    • broadcastMessage(message string):将消息广播给所有客户端。

    • main():启动服务器,监听客户端连接。

代码运行流程

  1. 启动服务器

    go复制

    listener, err := net.Listen("tcp", "0.0.0.0:8080")
    • 监听 0.0.0.0:8080 端口。

    • 如果监听失败,打印错误信息并退出。

  2. 接受客户端连接

    go复制

    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("Error accepting connection:", err)
            continue
        }
        go handleClient(conn)
    }
    • 循环接受客户端连接。

    • 每次接受到连接后,启动一个协程处理该客户端。

  3. 处理客户端连接

    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 映射中。

    • 广播新用户加入的消息。

    • 循环读取客户端发送的消息,并广播给所有其他客户端。

    • 如果客户端断开连接,移除该客户端并广播离开消息。

  4. 广播消息

    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 保护共享资源,确保并发访问的安全性。

复制

再试一次

分享

服务器如何处理多个客户端连接?

客户端断开连接后,服务器如何通知其他用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值