golang socket

服务端 server/main.go

package main

import (
    "fmt"
    "log"
    "net"
)

var clients = make(map[net.Conn]bool)

func handleConnection(conn net.Conn) {
    defer func() {
        if _, ok := clients[conn]; ok {
            delete(clients, conn)
        }
        conn.Close()
    }()

    clients[conn] = true

    for {
        p := make([]byte, 1024)
        n, err := conn.Read(p)
        if err != nil {
            log.Println("conn.Read err:", err)
            return
        }

        fmt.Println(conn.RemoteAddr().String(), string(p[:n]))

        _, err = conn.Write(p[:n])
        if err != nil {
            log.Println("conn.Write err:", err)
            return
        }
    }
}

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

    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Println("ln.Accept err:", err)
            continue
        }
        go handleConnection(conn)
    }
}

客户端 client/main.go

package main

import (
    "fmt"
    "log"
    "net"
    "time"
)

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

    go func() {
        for {
            p := make([]byte, 1024)
            n, err := conn.Read(p)
            if err != nil {
                log.Println("conn.Read err:", err)
                return
            }
            fmt.Println("收到消息:", string(p[:n]))
        }
    }()

    for {
        fmt.Print("请输入:")
        var message string
        fmt.Scanln(&message)
        _, err := conn.Write([]byte(message))
        if err != nil {
            log.Println("conn.Write err:", err)
            return
        }

        time.Sleep(250 * time.Millisecond)
    }
}

封包拆包

// math.MaxUint32
// binary.BigEndian.PutUint32()
func pack(data []byte) []byte {
    length := len(data)
    packedData := make([]byte, 4+length)
    copy(packedData[4:], data)
    copy(packedData, []byte{byte(length >> 24), byte(length >> 16), byte(length >> 8), byte(length)})
    return packedData
}

// binary.BigEndian.Uint32()
func unpack(packedData []byte) ([]byte, error) {
    packedDataLen := len(packedData)
    if packedDataLen < 4 {
        return nil, fmt.Errorf("not enough bytes to unpack")
    }
    length := int(packedData[0])<<24 | int(packedData[1])<<16 | int(packedData[2])<<8 | int(packedData[3])
    if packedDataLen < 4+length {
        return nil, fmt.Errorf("not enough bytes to unpack")
    }
    return packedData[4 : 4+length], nil
}