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)
    }
}
相关推荐
朴实赋能2 小时前
人工智能大模型+智能体:建筑行业数字化转型的“三级金字塔“实践路径
java·后端·struts
u0104058362 小时前
使用Spring Boot实现配置中心
java·spring boot·后端
gjxDaniel2 小时前
JavaScript编程语言入门与常见问题
开发语言·javascript
那我掉的头发算什么2 小时前
【Spring MVC】手动做出小网页的最后一步——学会SpringMVC响应
java·服务器·后端·spring·mvc
kk哥88992 小时前
C++新手入门
开发语言·c++
小楼v2 小时前
常见的java线程并发安全问题八股
java·后端·线程·并发安全
齐 飞2 小时前
springboot发送邮件
java·spring boot·后端
Hello eveybody2 小时前
Java发明者介绍
java·开发语言
Coding茶水间2 小时前
基于深度学习的红外镜头下的行人识别系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
开发语言·人工智能·深度学习·yolo·目标检测·机器学习