Go 添加到通过TCP发送的字符串中的不需要的空格
我正在尝试学习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
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
。
请参阅aboutbytes.newBuffer
,它明确指出,如果要为某些预分配方案提供缓冲区,则需要长度为零但为正的容量。服务器处理程序中的行
filename := bytes.NewBuffer(make([]byte, filenameSize))
如果是错的,请重新贴上
var filename bytes.Buffer
表达式make([]字节,文件名)
创建一个带有初始值的切片
长度filenameSize
用类型byte
的空值填充,因此0
bytes.NewBuffer
使用此片的初始内容创建一个缓冲区,并将附加到此片。所以你没有得到太多,你从太多开始
看
对于make
。
请参阅aboutbytes.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更有效。