Documentation ¶
Overview ¶
Package network implements a communication layer with a server and a client. Clients can connect to servers and receive and send messages. Depending on the implementation, communication may differ.
srv := network.NewTCPServer(zerolog.Nop()) // or any other available server srv.OnConnect(handleConnection) if err := srv.Open(":3900"); err != nil { panic(err) }
In the above example, handleConnection is a func that accepts a network.Conn as parameter. Do with this connection what you'd like. The connections have an ID.
func handleConnection(conn network.Conn) { loginMsg, err := conn.Receive() // receive a message // handle loginMsg and err // create loginResponse err = conn.Send(loginResponse) // send a message // handle err connectionPool.Add(conn) // remember the connection for further use }
To connect to the above server, do as follows.
conn, err := network.DialTCP(":3900") // or any other available dial method // handle err defer conn.Close() err = conn.Send(loginMsg) // send a message // handle err loginResponse, err := conn.Receive() // receive a message
Please note, that the dial functions will only work with the respective server, e.g. DialTCP will only work on TCPServers.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Conn ¶
type Conn interface { io.Closer // ID returns the ID of this connection. It can be used to uniquely identify // this connection globally. ID() ID // Send sends the given payload to the remote part of this connection. The // message will not be chunked, and can be read with a single call to // Conn.Receive. Send(context.Context, []byte) error // Receive reads a whole message and returns it in a byte slice. A message // is a byte slice that was sent with a single call to Conn.Send. Receive(context.Context) ([]byte, error) }
Conn describes a network connection. One can send a message with Conn.Send, and receive one with Conn.Receive. Unlike an io.Writer, the data that is passed into Send is guaranteed to be returned in a single Receive call on the other end, meaning that you don't have to worry about where your messages end. Maximum message length is 2GiB.
type ConnHandler ¶
type ConnHandler func(Conn)
ConnHandler is a handler function for handling new connections. It will be called with a fully initialized Conn, and is used as a callback in the server.
type Error ¶
type Error string
Error is a helper type for creating constant errors.
const ( // ErrOpen indicates, that the component was already opened, and it is // unable to be opened another time. ErrOpen Error = "already open" // ErrClosed indicates, that the component is already closed, and it cannot // be used anymore. ErrClosed Error = "already closed" // ErrTimeout indicates, that a the operation took longer than allowed. // Maybe there was a deadline from a context. ErrTimeout Error = "timeout" )
type ID ¶
ID describes an identifier that is used for connections. An ID has to be unique application-wide. IDs must not be re-used.
type Server ¶
type Server interface { io.Closer // Open opens the server on the given address. To make the server choose a // random free port for you, specify a port ":0". Open(string) error // Listening can be used to get a signal when the server has allocated a // port and is now actively listening for incoming connections. Listening() <-chan struct{} // Addr returns the address that this server is listening to. Addr() net.Addr // OnConnect sets a callback that will be executed whenever a new connection // connects to this server. OnConnect(ConnHandler) }
Server describes a server component, that listens for connecting clients. Before opening, it is recommended that one sets a connect handler with Server.OnConnect. A server can only be opened once. Closing a server must not close the accepted connections, but must only stop accepting new connections and release the allocated address.
Example ¶
package main import ( "context" "fmt" "log" "github.com/TimSatke/add/internal/network" "github.com/rs/zerolog" ) func main() { // When using, please don't ignore all the errors as we do here. ctx := context.Background() srv := network.NewTCPServer(zerolog.Nop()) // or whatever server is available srv.OnConnect(func(conn network.Conn) { _ = conn.Send(ctx, []byte("Hello, World!")) }) go func() { if err := srv.Open(":59513"); err != nil { log.Fatal(err) } }() <-srv.Listening() // wait for the server to come up client, _ := network.DialTCP(ctx, ":59513") defer func() { _ = client.Close() }() received, _ := client.Receive(ctx) fmt.Println(string(received)) }
Output: Hello, World!
func NewTCPServer ¶
NewTCPServer creates a new ready to use TCP server that uses the given logger.