在Go中通过套接字发送int64的正确方法
I'm trying to send a int64 over a TCP in golang, however, my receiver prints gets a different number then what I've sent out. What is the proper way to accomplish this?
//Buffer on both client and server
buffer := make([]byte, 1024)
//Sender
fileInfo, error := os.Stat(fileName)
if error != nil {
fmt.Println("Error opening file")
}
var fSize int = int(fileInfo.Size())
connection.Write([]byte(string(fSize)))
//Receiver
connection.Read(buffer)
fileSize := new(big.Int).SetBytes(bytes.Trim(buffer, "\x00")).Int64()
if err != nil {
fmt.Println("not a valid filesize")
fileSize = 0
}
我正在尝试通过golang中的TCP发送int64,但是我的接收方打印得到一个不同的数字,然后 我发出的。 p>
//客户端和服务器上的缓冲区
buffer:= make([] byte,1024)
// Sender
fileInfo,错误:= os.Stat(fileName)
if错误!= nil {
fmt.Println(“打开文件时发生错误”)
}
var fSize int = int(fileInfo.Size())
\ nconnection.Write([] byte(string(fSize)))
// Receiver
connection.Read(buffer)
fileSize:= new(big.Int).SetBytes(bytes.Trim(buffer) ,“ \ x00”))。Int64()
if err!= nil {
fmt.Println(“无效的文件大小”)
fileSize = 0
}
code> pre> \ n div>
Using binary.Write
/ binary.Read
:
//sender
err := binary.Write(connection, binary.LittleEndian, fileInfo.Size())
if err != nil {
fmt.Println("err:", err)
}
//receiver
var size int64
err := binary.Read(connection, binary.LittleEndian, &size)
if err != nil {
fmt.Println("err:", err)
}
[]byte(string(fSize))
doesn't do what you think it does, it treats the number as unicode character, it doesn't return the string representation of it.
If you want the string representation of a number, use strconv.Itoa
, if you want the binary represention then use:
num := make([]byte, 8) // or 4 for int32 or 2 for int16
binary.LittleEndian.PutUint64(num, 1<<64-1)
You can't use string() to cast from an int, you need to use the strconv package.
connection.Write([]byte(strconv.FormatInt(fileInfo.Size(), 10))
Use binary.BigEndian or binary.LittleEndian to encode the integer:
var size int64
// Send
var buf [8]byte
binary.BigEndian.PutUint64(buf[:], uint64(size))
_, err := w.Write(buf[:])
// Receive
var buf [8]byte
_, err := io.ReadFull(r, buf[:])
if err != nil {
// handle error
}
size = int64(binary.BigEndian.Uint64(buf[:])
You can also use the binary.Read and binary.Write. Your application code will be a little shorter at the cost of type switches and other goo inside these functions.
A couple of points about the code in the question. The conversion
string(fSize)
returns the UTF-8 representation of the rune fSize. It does not return a decimal encoding or binary encoding the value. Use the strconv packate to convert a numeric value to a decimal representation. Use the above mentioned binary package to convert to binary representation.
The sequence
connection.Read(buffer)
buffer = bytes.Trim(buffer, "\x00")
trims away real data if the data happens to include a 0 byte at the ends. Read returns the number of bytes read. Use that length to slice the buffer:
n, err := connection.Read(buffer)
buffer = buffer[:n]