go - 不正确的数据重传

标签 go connection buffer slice

我需要我的程序处于连接中间并在两个方向上正确传输数据。我写了这段代码,但它不能正常工作

package main

    import (
        "fmt"
        "net"
)

func main() {
    listener, err := net.Listen("tcp", ":8120")

    if err != nil {
        fmt.Println(err)
        return
    }
    defer listener.Close()
    fmt.Println("Server is listening...")
    for {
        var conn1, conn2 net.Conn
        var err error
        conn1, err = listener.Accept()
        if err != nil {
            fmt.Println(err)
            conn1.Close()
            continue
        }
        conn2, err = net.Dial("tcp", "185.151.245.51:80")
        if err != nil {
            fmt.Println(err)
            conn2.Close()
            continue
        }
        go handleConnection(conn1, conn2)
        go handleConnection(conn2, conn1)
    }
}

func handleConnection(conn1, conn2 net.Conn) {
    defer conn1.Close()
    for {
        input := make([]byte, 1024)
        n, err := conn1.Read(input)
        if n == 0 || err != nil {
            break
        }
        conn2.Write([]byte(input))
    }
}

问题是数据损坏了, 例如。 enter image description here 左边一个是原装的,右边一个是我买的。 最终得到的文件的结尾是不可读的。 enter image description here 但一开始一切正常。 我试图更改输入 slice 大小。如果大小 > 0 且 < 8,一切都很好,但速度很慢。如果我将输入大小设置得非常大,数据损坏会变得更加糟糕。 我做错了什么?

最佳答案

handleConnection 中,无论 conn1.Read 返回什么,您总是写入 1024 个字节。

你想这样写数据:

conn2.Write(input[:n])

您还应该检查顶级 for 循环。你确定你不接受多个连接并将它们全部混在一起吗?我会加入一些日志语句,以便您可以查看何时建立和关闭连接。

另一个(可能无关紧要的)错误是您将 n==0 视为终止条件。 In the documentation of io.Reader建议您忽略 n==0, err==nil。如果不检查代码,我无法确定,但我希望 conn.Read 永远不会返回 n==0, err==nil,所以这不太可能给你添麻烦了。

虽然它不影响正确性,但您也可以将 input 的定义移出循环,以便在每次迭代中重用它;它可能会减少垃圾收集器必须完成的工作量。

关于go - 不正确的数据重传,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50525268/

相关文章:

postgresql - 在 Go 语言中运行 SQL 查询时 PQ 关系不存在

sorting - go type conversion - 使用共享接口(interface)对 2 片不同的接口(interface)进行排序

linux - Debian 7 : connection problems and timeouts

mysql - 如何处理 "Unable to connect to any of the specified MySQL hosts."

Java 逻辑 - while 循环中发生的奇怪事情

c++ - istream std::cin 如何修改自定义 istream 缓冲区?

go - 有没有办法在微服务前面实现 SSO?

database - 使用服务名称从 Eclipse 连接到 Oracle Enterprise 11

c++ - 了解着色器编程

go - 如何调试特定功能?