Search code examples
socketsgounix-socket

Can golang net.Conn get notified when there is a new message?


What I try to implement

I'm implementing a client sending and receiving unixpackets and interacting with a server which was already implemented in C++.
So far, the client can receive and send packet to server successfully. But I used a for loop to keep calling Recv to see if there is a new message.

What I did

I implemented a Packet class so that the client and server can follow the same rules to encode and decode the message. Transport is a struct wrapping a net.Conn. Client is consisted of Transport, receiving Packet and sending Packet.
I used a for loop to keep calling Recv to see if there's a new message arriving at net.Conn.

type Packet struct {
    Length      uint32
    Data        []byte
    ReadOffset  uint32
    WriteOffset uint32
}

type Transport struct {
    url   string
    conn  net.Conn
}

// connect to url
func (transport *Transport) Dial(url string) error {
    c, err := net.Dial("unixpacket", url)
    if err != nil {
        return err
    }
    transport.url = url
    transport.conn = c
    return nil
}

// sending Packet
func (transport *Transport) Send(p *Packet) bool {
    readBuffer := (p.Data)[p.ReadOffset : p.WriteOffset]
    _, err := transport.conn.Write(readBuffer)
    if err != nil {
        return false
    }
    return true
}

// receiving Packet
func (transport *Transport) Recv(p *Packet) bool {
    writeBuffer := (p.Data)[p.WriteOffset :]
    _, err := transport.conn.Read(writeBuffer)
    if err != nil {
        return false
    }
    return true
}

type Client struct {
    Transport  *Transport
    RecvPacket *Packet
    SendPacket *Packet
}

// keep checking transport
func (c *Client) ReadFromTransport() {
    for {
        time.Sleep(20 * time.Millisecond)
        if c.Transport.Recv(c.RecvPacket) == false {
            continue
        }
    }
}

Question

Is there a method to have the net.Conn get notified when a new message arriving instead of using a for loop?


Solution

  • Is there a method to have the net.conn get notified when a new message arriving net.conn instead of using a for loop?

    No, not in the standard packages.

    Read()ing from net.Conn in a loop is the usual way to detect message arrival. If you need to perform multiple concurrent tasks, you can encapsulate the loop in a goroutine writing to a channel and wrap a for-loop plus select around reading from that channel.

    Outside of standard packages, you can explore event-driven IO with projects like https://github.com/tidwall/evio