1、IM:基础连接

IM:基础连接

1、服务端

go 复制代码
// server.go
package main

import (
    "bufio"
    "fmt"
    "net"
    "strings"
    "sync"
)

var (
    clients = make(map[net.Conn]string)
    mu      sync.Mutex
)

func broadcast(msg string, sender net.Conn) {
    mu.Lock()
    defer mu.Unlock()

    for conn := range clients {
        if conn != sender {
            fmt.Fprintln(conn, msg)
        }
    }
}

func handleClient(conn net.Conn) {
    defer conn.Close()

    // 读取用户名(第一行)
    reader := bufio.NewReader(conn)
    username, err := reader.ReadString('\n')
    if err != nil {
        fmt.Println("Error reading username:", err)
        return
    }
    username = strings.TrimSpace(username)
    if username == "" {
        username = "Anonymous"
    }

    mu.Lock()
    clients[conn] = username
    mu.Unlock()

    fmt.Printf("User %s joined.\n", username)
    broadcast(fmt.Sprintf("[Server] %s joined the chat.", username), conn)

    // 广播消息循环
    for {
        msg, err := reader.ReadString('\n')
        if err != nil {
            break
        }
        msg = strings.TrimSpace(msg)
        if msg == "" {
            continue
        }
        fullMsg := fmt.Sprintf("[%s] %s", username, msg)
        fmt.Println(fullMsg) // 服务端日志
        broadcast(fullMsg, conn)
    }

    // 用户断开
    mu.Lock()
    delete(clients, conn)
    mu.Unlock()
    broadcast(fmt.Sprintf("[Server] %s left the chat.", username), nil)
    fmt.Printf("User %s disconnected.\n", username)
}

func main() {
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        panic(err)
    }
    defer listener.Close()

    fmt.Println("IM Server started on :8080")

    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("Accept error:", err)
            continue
        }
        go handleClient(conn)
    }
}

2、客户端

go 复制代码
// client.go
package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
    "strings"
)

func main() {
    conn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        panic(err)
    }
    defer conn.Close()

    fmt.Print("Enter your username: ")
    reader := bufio.NewReader(os.Stdin)
    username, _ := reader.ReadString('\n')
    username = strings.TrimSpace(username)

    // 发送用户名
    fmt.Fprintln(conn, username)

    // 启动 goroutine 接收消息
    go func() {
        in := bufio.NewScanner(conn)
        for in.Scan() {
            fmt.Println(in.Text())
        }
    }()

    // 主线程发送消息
    for {
        fmt.Print("> ")
        msg, _ := reader.ReadString('\n')
        msg = strings.TrimSpace(msg)
        if msg == "/quit" {
            break
        }
        fmt.Fprintln(conn, msg)
    }
}
相关推荐
一只叫煤球的猫1 分钟前
Spring AI 2.0 源码解析(四):Prompt、Message、Options 的对象模型
后端·面试·ai编程
名字还没想好☜4 分钟前
Spring @EventListener 事件驱动解耦实战:同步转异步、事务绑定与顺序控制
java·数据库·后端·python·spring
可乐鸡翅yeah_15 分钟前
hls.js 播放质量埋点实战,采集卡顿、起播、错误指标定位线上用户问题
开发语言·前端·javascript·ecmascript·音视频·m3u8·音视频在线播放
szarron32 分钟前
RF Demo Kit|NanoVNA 射频演示测试板完整上手教程,滤波器、衰减器、SOLT 校准学习板
开发语言·人工智能·学习·php·射频工程·频谱仪
边境悍匪43 分钟前
蜗牛学苑 Java 智能体学习 Day39|SpringAI 会话存储、Function‑Call 工具调用、MCP 思维导图复盘
java·开发语言·spring boot·学习·阿里云
万物智能信息科技1 小时前
RK3568 的多路显示移植—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
linux·开发语言·华为·开源·harmonyos
掘金挖土1 小时前
前端手摸手跑路之 AI 应用开发(三)
前端·后端
蓝悦无人机1 小时前
Qt Design Studio(QDS)4.8.2项目文件结构详解
开发语言·qt·qt creator·qds·项目文件结构·qtc
胡写代码1 小时前
若依 + MyBatis-Plus,分页为什么悄悄失效了?
java·后端
yxlalm1 小时前
4.java秒杀项目第四课-后端商品后台接口
java·开发语言