服务器卡住,在 Golang 中,没有得到响应

问题描述 投票:0回答:1

我是 Golang 新手,正在尝试用 Go 构建 Redis 服务器。 该代码在并发解析逻辑之前运行。 此解析逻辑可以很好地发送响应。 现在突然没有得到任何回应, 当我收到客户端的请求时,服务器和客户端都受到了影响。 当我在客户端点击 control +c 时,我会在服务器终端上获得所有打印语句。 但客户端没有任何反应。

代码有问题吗?

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "io"
    "net"
    "os"
    "strconv"
    "strings"
)

const seperator = "\r\n"

func main() {
    fmt.Println("Logs from your program will appear here!")

    l, err := net.Listen("tcp", "0.0.0.0:6379")
    if err != nil {
        fmt.Println("Failed to bind to port 6379", err.Error())
        os.Exit(1)
    }

    defer l.Close()
    for {
        conn, err := l.Accept()
        if err != nil {
            fmt.Println("Unable to accept the connection", err.Error())
            continue
        }
        go handleConnection(conn)

    }
}

func handleConnection(c net.Conn) {
    defer c.Close()

    reader := bufio.NewReader(c)

    requests := parser(reader)

    if len(requests) < 1 {
        fmt.Println("No requests or Something Wrong with Request Format")
    }

    for i := 0; i < len(requests); i++ {
        subRequest := requests[i]

        currentCommand := subRequest[0]

        if strings.ToUpper(currentCommand) == "ECHO" {
            response := echoHandler(subRequest)
            if response == "" {
                fmt.Println("bad response")
            }
            fmt.Println("response", response)
            _, err := c.Write([]byte(response))

            if err != nil {
                fmt.Println("something went wrong while repsondiong", err.Error())
            }
        }
    }
}

func echoHandler(subrequest []string) string {
    if len(subrequest) != 2 {
        fmt.Println("Invalid Request Format")
        return ""
    }

    response := encoder(subrequest[1])
    return response
}

func encoder(response string) string {
    res := "$"
    res += strconv.Itoa(len(response))
    res += seperator
    res += response
    res += seperator
    fmt.Println(res)
    return res

}

func parser(buffer *bufio.Reader) [][]string {
    requests := [][]string{}

    // We are parsing the request into multiple Commands
    // Each command starts with *<int>, <int> represents number of parameters, and there could be multiple requests.

    var buf bytes.Buffer
    _, err := io.Copy(&buf, buffer)
    if err != nil {
        panic(err)
    }

    request := buf.String()
    println("Complete request:", request)

    //Lets get all the subrequests that are there in this main request
    subRequests := strings.Split(request, "*")

    println("subrequests", subRequests)

    for _, subreq := range subRequests {

        if subreq == "" {
            continue
        }

        // Each command is madeup of multiple lines, we are parsing the lines here
        linesOfCommand := strings.Split(subreq, "\r\n")

        println("subreq", subreq)
        println("linesOfCommand", linesOfCommand)

        if len(linesOfCommand) < 2 {
            continue
        }

        //First line in each command represents numberofparameters
        numberOfParamters, err := strconv.Atoi(linesOfCommand[0])

        if err != nil {
            fmt.Println("Invalid Command, unable to read number of parameters", err.Error())
            continue
        }

        commands := []string{}
        for i := 0; i < numberOfParamters; i++ {
            lineIndex := i*2 + 2
            if lineIndex >= len(linesOfCommand) {
                fmt.Println("Command Length Mismatch")
                continue
            }
            commands = append(commands, linesOfCommand[lineIndex])
        }

        requests = append(requests, commands)
    }

    return requests
}

代码有什么问题,有没有办法更好地编写服务器输入处理

go redis concurrency
1个回答
0
投票

_, err := io.Copy(&buf, buffer)
中的这行
parser()
导致了错误。

io.Copy
从 src 复制到 dst,直到 src 达到 EOF 或发生错误。您的 src(缓冲区)是一个 TCP 连接,其关闭时会到达 EOF。这就是为什么您在关闭客户端后会收到处理程序的响应。

解决这个问题非常简单:每次从连接中读取确切数量的字节。

© www.soinside.com 2019 - 2024. All rights reserved.