Golang数据包结构返回缓冲区

huangapple go评论84阅读模式
英文:

Golang packet strcuture returning buffer

问题

我已经创建了一个带有包结构的数据包包装器,如下所示:

// 数据包缓冲对象
package Packet

import (
    "bytes"
    "encoding/binary"
)

type Packet struct {
    buffer bytes.Buffer
}

func (p Packet) GetBytes() []byte {
    return p.buffer.Bytes()
}

func (p Packet) AddString(s string) {
    p.buffer.Write([]byte(s))
}

func (p Packet) AddInt(i_ int) {
    // 将整数转换为字节
    b := make([]byte, 2)
    binary.LittleEndian.PutUint16(b, uint16(i_))
    // 将字节写入缓冲区
    p.buffer.Write([]byte(b))
}

func (p Packet) AddByte(b []byte) {
    p.buffer.Write(b)
}

这是一个使用包结构来组装数据包并发送给客户端的会话包装器:

package Session

type MapleSession struct {
    connection net.Conn
    EncryptIV, DecryptIV []byte
    isConnected bool
}

func (session *MapleSession) Run(conn net.Conn) { 
    // 显示新连接的来源
    session.connection = conn
    fmt.Println("Client connected from:", session.connection.RemoteAddr())
    
    // 设置用户连接变量为true
    session.isConnected = true
    
    // 发送握手包
    packet := MaplePacket.CreateHandShake(&session.EncryptIV, &session.DecryptIV, 40, "", []byte("0x05"))
    session.connection.Write(packet)
}

这是MaplePacket包,它创建了从会话包装器请求的要发送给客户端的数据包:

package MaplePacket

func CreateHandShake (eIV, dIV *[]byte, version int, location string, locale []byte) []byte{
    packet := Packet.Packet{}

    // 创建IVs
    *eIV = (make([]byte, 4))
    n1, _ := rand.Read(*eIV)
    *dIV = (make([]byte, 4))
    n2, _ := rand.Read(*dIV)
    
    if (n1 + n2 < 8) {
        fmt.Println("Error in IV generation")
    }    
    
    // 创建数据包
    packet.AddInt(version)
    packet.AddString(location)
    packet.AddByte(*dIV)
    packet.AddByte(*eIV)
    packet.AddByte(locale)
    
    fmt.Println(packet.GetBytes())
    
    return packet.GetBytes()
}

然而,当像上面的示例那样创建数据包并添加值时,Packet.GetBytes() 返回一个空数组。使用 bytes.Buffer 是正确的方法吗?还是我在处理方式上完全错误了?

英文:

I have made a packet package with a packet structure inside like so:

//A packet buffer object
package Packet

import (
    &quot;bytes&quot;
    &quot;encoding/binary&quot;
)

type Packet struct {
    buffer bytes.Buffer
}

func (p Packet) GetBytes() []byte {
    return p.buffer.Bytes()
}

func (p Packet) AddString(s string) {
    p.buffer.Write([]byte(s))
}

func (p Packet) AddInt(i_ int) {
    //Convert int to byte
    b := make([]byte, 2)
    binary.LittleEndian.PutUint16(b, uint16(i_))
    //Push byte to buffer
    p.buffer.Write([]byte(b))
}

func (p Packet) AddByte(b []byte) {
    p.buffer.Write(b)
}

This is the session package that uses the packet structure to form packets and send them to the client

package Session

type MapleSession struct {
    connection net.Conn
    EncryptIV, DecryptIV []byte
    isConnected bool
}

func (session *MapleSession) Run(conn net.Conn) { 
    //Display where the new connection is coming from
    session.connection = conn
    fmt.Println(&quot;Client connected from:&quot;, session.connection.RemoteAddr())
    
    //Set the user connected variable on
    session.isConnected = true
    
    //Send Handshake
    packet := MaplePacket.CreateHandShake(&amp;session.EncryptIV, &amp;session.DecryptIV, 40, &quot;&quot;, []byte(&quot;0x05&quot;))
    session.connection.Write(packet)
}

This is the MaplePacket package that creates the packets to send to the client that are requested from the session package

package MaplePacket

func CreateHandShake (eIV, dIV *[]byte, version int, location string, locale []byte) []byte{
    packet := Packet.Packet{}

    //Create IVs
    *eIV = (make([]byte, 4))
    n1, _ := rand.Read(*eIV)
    *dIV = (make([]byte, 4))
    n2, _ := rand.Read(*dIV)
    
    if (n1 + n2 &lt; 8) {
        fmt.Println(&quot;Error in IV generation&quot;)
    }    
    
    //Create the packet
    packet.AddInt(version)
    packet.AddString(location)
    packet.AddByte(*dIV)
    packet.AddByte(*eIV)
    packet.AddByte(locale)
    
    fmt.Println(packet.GetBytes())
    
    return packet.GetBytes()
}

However when creating a packet like in the example above and adding values, the Packet.GetBytes() returns an empty array. Is bytes.Buffer the correct way to go about this is? Or am I going completely wrong in how I am approaching this?

答案1

得分: 6

Go通过值传递的方式传递所有参数,包括接收器。

尝试使用指针接收器:(p *Packet)bytes.Buffer包含被丢弃的状态信息。

你的Package类型等效于以下内容:

type Packet struct {
	buffer /* bytes.Buffer */ struct {
		buf       []byte            // contents are the bytes buf[off : len(buf)]
		off       int               // read at &buf[off], write at &buf[len(buf)]
		runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune
		bootstrap [64]byte          // memory to hold first slice; helps small buffers (Printf) avoid allocation.
		lastRead  readOp            // last read operation, so that Unread* can work correctly.
	}
}

你将一个Package类型的变量的副本(按值)传递给方法。副本会被更新以反映新的状态,并在返回后被丢弃。

英文:

Go passes all arguments, including receivers, by value.

Try using pointer receivers: (p *Packet). bytes.Buffer contains state information which is being discarded.


> package bytes
>
> // Simple byte buffer for marshaling data.
> // A Buffer is a variable-sized buffer of bytes with Read and Write methods.
> // The zero value for Buffer is an empty buffer ready to use.
> type Buffer struct {
> buf []byte // contents are the bytes buf[off : len(buf)]
> off int // read at &buf[off], write at &buf[len(buf)]
> runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune
> bootstrap [64]byte // memory to hold first slice; helps small buffers (Printf) avoid allocation.
> lastRead readOp // last read operation, so that Unread* can work correctly.
> }


> The Go Programming Language
>
> Effective Go
>
> Methods
>
> Pointers vs. Values
>
> The rule about pointers vs. values for receivers is that value methods
> can be invoked on pointers and values, but pointer methods can only be
> invoked on pointers. This is because pointer methods can modify the
> receiver; invoking them on a copy of the value would cause those
> modifications to be discarded.

Your type Package type is equivalent to the following.

type Packet struct {
	buffer /* bytes.Buffer */ struct {
	buf       []byte            // contents are the bytes buf[off : len(buf)]
	off       int               // read at &amp;buf[off], write at &amp;buf[len(buf)]
	runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune
	bootstrap [64]byte          // memory to hold first slice; helps small buffers (Printf) avoid allocation.
	lastRead  readOp            // last read operation, so that Unread* can work correctly.
}

You pass a copy (by value) of a Package type variable to the methods. The copy is updated to reflect the new state and, upon return is discarded.

huangapple
  • 本文由 发表于 2014年5月31日 20:29:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/23970090.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定