Akzeptieren Sie eine dauerhafte TCP-Verbindung in Golang Server

Ich experimentiere mit Go und möchte einen TCP-Server erstellen, zu dem ich telneten, Befehle senden und Antworten empfangen kann.

const (
    CONN_HOST = "localhost"
    CONN_PORT = "3333"
    CONN_TYPE = "tcp"
)

func main() {

    listener, err := net.Listen(CONN_TYPE, fmt.Sprintf("%s:%s", CONN_HOST, CONN_PORT))
    if err != nil {
        log.Panicln(err)
    }

    defer listener.Close()

    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Panicln(err)
        }

        go handleRequest(conn)
    }
}

func handleRequest(conn net.Conn) {
    buffer := make([]byte, 1024)

    length, err := conn.Read(buffer)
    if err != nil {
        log.Panicln(err)
    }

    str := string(buffer[:length])

    fmt.Println(conn.RemoteAddr().String())
    fmt.Printf("Received command %d\t:%s\n", length, str)

    switch str {
        case "PING\r\n":
        sendResponse("PONG", conn)
        case "PUSH\r\n":
        sendResponse("GOT PUSH", conn)
    default:
        conn.Write([]byte(fmt.Sprintf("UNKNOWN_COMMAND: %s\n", str)))
    }

    conn.Close() // closes the connection
}

func sendResponse(res string, conn net.Conn) {
    conn.Write([]byte(res+"\n"))
}

Das obige Snippet beendet jedes Mal die Verbindung und wirft mich aus der Terminalsitzung. Eigentlich möchte ich jedoch, dass die Verbindung für weitere E / A-Vorgänge geöffnet bleibt. Wenn ich einfach das @ entferconn.Close(), dann scheint der Server irgendwo zu hängen, da er keine weiteren Antworten erhält.

Die Art und Weise, wie ich das gelöst habe, besteht darin, meine handleRequest-Methode endlos zu schleifen, sodass sie niemals beendet wird, bis sie ein @ empfängQUIT\r\n Botschaft. Ist das angemessen - oder gibt es einen besseren Weg, dies zu erreichen?

func handleRequest(conn net.Conn) {
    for {
        log.Println("Handling Request")
        buffer := make([]byte, 1024)

        length, err := conn.Read(buffer)
        if err != nil {
            log.Panicln(err)
        }

        str := string(buffer[:length])

        fmt.Println(conn.RemoteAddr().String())
        fmt.Printf("Received command %d\t:%s\n", length, str)

        switch str {
        case "PING\r\n":
            sendResponse("PONG", conn)
        case "PUSH\r\n":
            sendResponse("GOT PUSH", conn)
        case "QUIT\r\n":
            sendResponse("Goodbye", conn)
            conn.Close()
        default:
            conn.Write([]byte(fmt.Sprintf("UNKNOWN_COMMAND: %s\n", str)))
        }
    }
}

Antworten auf die Frage(4)

Ihre Antwort auf die Frage