Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 添加到通过TCP发送的字符串中的不需要的空格_Go - Fatal编程技术网

Go 添加到通过TCP发送的字符串中的不需要的空格

Go 添加到通过TCP发送的字符串中的不需要的空格,go,Go,我正在尝试学习Go,我尝试的第一件事是使用TCP在客户端和服务器之间发送文件。我使用net.Listen建立连接,并使用net.Dial进行连接。我的客户逻辑是: 使用二进制文件发送int64。写入描述文件名大小的 使用io.WriteString发送文件名 发送一个描述文件大小的int64 使用io.CopyN发送文件 我的服务器逻辑是: 使用二进制读取8个字节。读取,另存为N 读取Nbytes以获取文件名,该文件名被读入一个bytes.NewBuffer(make([]byte,filena

我正在尝试学习Go,我尝试的第一件事是使用TCP在客户端和服务器之间发送文件。我使用
net.Listen
建立连接,并使用
net.Dial进行连接。我的客户逻辑是:

  • 使用
    二进制文件发送int64。写入描述文件名大小的
  • 使用io.WriteString发送文件名
  • 发送一个描述文件大小的int64
  • 使用
    io.CopyN发送文件
  • 我的服务器逻辑是:

  • 使用
    二进制读取8个字节。读取
    ,另存为
    N
  • 读取
    N
    bytes以获取文件名,该文件名被读入一个
    bytes.NewBuffer(make([]byte,filenameSize))
    ,该文件随后调用了
    String()
  • 读取8个字节以获取文件大小,另存为
    M
  • io.CopyN
    从连接到新的文件对象,用于
    M
    字节
  • 我的问题完全让我困惑,我无法解决或理解,在谷歌上也找不到任何讨论或解决方案:即使文件名长度传输准确,服务器总是收到一个预期长度的两倍的文件名,其中前一半是空白。更令人困惑的是,使用
    strings.trimlefit(filename,”)
    从来都不起作用,即使它适用于我自己创建的字符串

    所以我完全不知道发生了什么,文档中也没有任何内容,所以,谷歌、go nuts等提到了任何可能相关的内容。不知道如何前进或思考这个问题,我希望得到一些帮助

    我的服务器处理程序:

    func handle(conn net.Conn) {
        defer conn.Close()
        conn.SetReadDeadline(time.Now().Add(time.Second * 30))
    
        var filenameSize int64
        err := binary.Read(conn, binary.LittleEndian, &filenameSize)
        check(err)
    
        filename := bytes.NewBuffer(make([]byte, filenameSize))
        bytesRead, err := io.CopyN(filename, conn, filenameSize)
        fmt.Printf("Expected %d bytes for filename, read %d bytes\n", filenameSize, bytesRead)
        str := filename.String()
        fmt.Println(strings.TrimLeft(str, " "))
    
        var filesize int64
        err = binary.Read(conn, binary.LittleEndian, &filesize)
        check(err)
        fmt.Printf("Expecting %d bytes in file\n", filesize)
    
        f, err := os.Create(str)
        check(err)
        bytesWritten, err := io.CopyN(f, conn, filesize)
        check(err)
        fmt.Printf("Transfer complete, expected %d bytes, wrote %d bytes", filesize, bytesWritten)
        if filesize != bytesWritten {
            fmt.Printf("ERROR! File doesn't match expected size!")
        }
    }
    
    我的客户:

    func main() {
        name := "test_file.doc"
    
        conn, err := net.Dial("tcp", "localhost:8250")
        check(err)
    
        length := int64(len(name))
        err = binary.Write(conn, binary.LittleEndian, length)
        check(err)
    
        bytes, err := io.WriteString(conn, name)
        check(err)
        if bytes != len(name) {
            fmt.Printf("Error! Wrote %d bytes but length of name is %d!\n", bytes, length)
        }
    
        f, err := os.Open(name)
        check(err)
    
        stat, err := f.Stat()
        check(err)
    
        filesize := stat.Size()
        err = binary.Write(conn, binary.LittleEndian, filesize)
        check(err)
    
        bytesWritten, err := io.CopyN(conn, f, filesize)
        check(err)
        if bytesWritten != filesize {
            fmt.Printf("Error! Wrote %d bytes but length of file is %d!\n", bytes, stat.Size())
        }
    }
    

    服务器处理程序中的行

    filename := bytes.NewBuffer(make([]byte, filenameSize))
    
    如果是错的,请重新贴上

    var filename bytes.Buffer
    
    表达式
    make([]字节,文件名)
    创建一个带有初始值的切片 长度
    filenameSize
    用类型
    byte
    的空值填充,因此
    0
    bytes.NewBuffer
    使用此片的初始内容创建一个缓冲区,并将附加到此片。所以你没有得到太多,你从太多开始

    看 对于
    make

    请参阅about
    bytes.newBuffer
    ,它明确指出,如果要为某些预分配方案提供缓冲区,则需要长度为零但为正的容量。

    服务器处理程序中的行

    filename := bytes.NewBuffer(make([]byte, filenameSize))
    
    如果是错的,请重新贴上

    var filename bytes.Buffer
    
    表达式
    make([]字节,文件名)
    创建一个带有初始值的切片 长度
    filenameSize
    用类型
    byte
    的空值填充,因此
    0
    bytes.NewBuffer
    使用此片的初始内容创建一个缓冲区,并将附加到此片。所以你没有得到太多,你从太多开始

    看 对于
    make
    。 请参阅about
    bytes.newBuffer
    ,它明确指出,如果要为某些预分配方案提供缓冲区,则需要长度为零但为正的容量

    制作切片、地图和频道

    Call             Type T     Result
    
    make(T, n)       slice      slice of type T with length n and capacity n
    make(T, n, m)    slice      slice of type T with length n and capacity m
    

    func新缓冲区(buf[]字节)*缓冲区

    NewBuffer创建并初始化一个新的缓冲区,使用buf作为其 初始内容。新缓冲区拥有buf的所有权,而 呼叫方在此呼叫后不应使用buf。NewBuffer的目的是 准备缓冲区以读取现有数据。它也可以用来调整大小 用于写入的内部缓冲区。要做到这一点,buf应该拥有 所需容量,但长度为零

    在大多数情况下,new(Buffer)(或仅声明一个Buffer变量)是 足以初始化缓冲区


    bytes.NewBuffer
    可用于调整内部写入缓冲区的大小。为此,buf应具有所需的容量,但长度为零。例如,长度为零,容量为filenameSize

    filename := bytes.NewBuffer(make([]byte, 0, filenameSize))
    
    filename := bytes.NewBuffer(make([]byte, filenameSize))
    
    在错误中,您分配了长度和容量为filenameSize的buf

    filename := bytes.NewBuffer(make([]byte, 0, filenameSize))
    
    filename := bytes.NewBuffer(make([]byte, filenameSize))
    

    制作切片、地图和频道

    Call             Type T     Result
    
    make(T, n)       slice      slice of type T with length n and capacity n
    make(T, n, m)    slice      slice of type T with length n and capacity m
    

    func新缓冲区(buf[]字节)*缓冲区

    NewBuffer创建并初始化一个新的缓冲区,使用buf作为其 初始内容。新缓冲区拥有buf的所有权,而 呼叫方在此呼叫后不应使用buf。NewBuffer的目的是 准备缓冲区以读取现有数据。它也可以用来调整大小 用于写入的内部缓冲区。要做到这一点,buf应该拥有 所需容量,但长度为零

    在大多数情况下,new(Buffer)(或仅声明一个Buffer变量)是 足以初始化缓冲区


    bytes.NewBuffer
    可用于调整内部写入缓冲区的大小。为此,buf应具有所需的容量,但长度为零。例如,长度为零,容量为filenameSize

    filename := bytes.NewBuffer(make([]byte, 0, filenameSize))
    
    filename := bytes.NewBuffer(make([]byte, filenameSize))
    
    在错误中,您分配了长度和容量为filenameSize的buf

    filename := bytes.NewBuffer(make([]byte, 0, filenameSize))
    
    filename := bytes.NewBuffer(make([]byte, filenameSize))
    

    请发布完整示例:您正在读取文件名的固定大小数据,只需使用正确大小的切片调用
    Read
    。请发布完整示例:您正在读取文件名的固定大小数据,只需使用正确大小的切片调用
    Read
    。在这种情况下,
    filename:=bytes.NewBuffer(make([]字节,0,filenameSize))
    ,一种精确分配,比
    var filename bytes.Buffer
    更有效。在这种情况下,
    filename:=bytes.NewBuffer(make([]字节,0,filenameSize))
    ,一种精确分配,比
    var filename bytes.Buffer更有效。