enet

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 13, 2024 License: MIT Imports: 6 Imported by: 0

README

go-enet

Enet bindings for Go using cgo.

Installation

First, you might need to install enet as a dependency:

  • Windows: Nothing to do - should work out of the box with the supplied headers and library.
  • Linux: Install the enet development package with your package manager.
    • On Debian-based systems: apt install libenet-dev
  • MacOS: Install the enet package with brew: brew install enet
$ go get github.com/codecat/go-enet

Usage

import "github.com/codecat/go-enet"

The API is mostly the same as the C API, except it's more object-oriented.

Server example

This is a basic server example that responds to packets "ping" and "bye".

package main

import (
	"github.com/codecat/go-enet"
	"github.com/codecat/go-libs/log"
)

func main() {
	// Initialize enet
	enet.Initialize()

	// Create a host listening on 0.0.0.0:8095
	host, err := enet.NewHost(enet.NewListenAddress(8095), 32, 1, 0, 0)
	if err != nil {
		log.Error("Couldn't create host: %s", err.Error())
		return
	}

	// The event loop
	for true {
		// Wait until the next event
		ev := host.Service(1000)

		// Do nothing if we didn't get any event
		if ev.GetType() == enet.EventNone {
			continue
		}

		switch ev.GetType() {
		case enet.EventConnect: // A new peer has connected
			log.Info("New peer connected: %s", ev.GetPeer().GetAddress())

		case enet.EventDisconnect: // A connected peer has disconnected
			log.Info("Peer disconnected: %s", ev.GetPeer().GetAddress())

		case enet.EventReceive: // A peer sent us some data
			// Get the packet
			packet := ev.GetPacket()

			// We must destroy the packet when we're done with it
			defer packet.Destroy()

			// Get the bytes in the packet
			packetBytes := packet.GetData()

			// Respond "pong" to "ping"
			if string(packetBytes) == "ping" {
				ev.GetPeer().SendString("pong", ev.GetChannelID(), enet.PacketFlagReliable)
				continue
			}

			// Disconnect the peer if they say "bye"
			if string(packetBytes) == "bye" {
				log.Info("Bye!")
				ev.GetPeer().Disconnect(0)
				continue
			}
		}
	}

	// Destroy the host when we're done with it
	host.Destroy()

	// Uninitialize enet
	enet.Deinitialize()
}

Client example

This is a basic client example that sends a ping to the server every second that there is no event.

package main

import (
	"github.com/codecat/go-enet"
	"github.com/codecat/go-libs/log"
)

func main() {
	// Initialize enet
	enet.Initialize()

	// Create a client host
	client, err := enet.NewHost(nil, 1, 1, 0, 0)
	if err != nil {
		log.Error("Couldn't create host: %s", err.Error())
		return
	}

	// Connect the client host to the server
	peer, err := client.Connect(enet.NewAddress("127.0.0.1", 8095), 1, 0)
	if err != nil {
		log.Error("Couldn't connect: %s", err.Error())
		return
	}

	// The event loop
	for true {
		// Wait until the next event
		ev := client.Service(1000)

		// Send a ping if we didn't get any event
		if ev.GetType() == enet.EventNone {
			peer.SendString("ping", 0, enet.PacketFlagReliable)
			continue
		}

		switch ev.GetType() {
		case enet.EventConnect: // We connected to the server
			log.Info("Connected to the server!")

		case enet.EventDisconnect: // We disconnected from the server
			log.Info("Lost connection to the server!")

		case enet.EventReceive: // The server sent us data
			packet := ev.GetPacket()
			log.Info("Received %d bytes from server", len(packet.GetData()))
			packet.Destroy()
		}
	}

	// Destroy the host when we're done with it
	client.Destroy()

	// Uninitialize enet
	enet.Deinitialize()
}

Documentation

Overview

Example (ClientServer)
// This example demonstrates some basic usage of the enet library.
// Here we set up a client & server, send a message between them, then
// disconnect & cleanup.

port := uint16(1234)

fmt.Printf("enet version: %s\n", enet.LinkedVersion())

// Initialize enet
enet.Initialize()

// Make our server.
server, err := enet.NewHost(enet.NewListenAddress(port), 32, 1, 0, 0)
if err != nil {
	log.Fatal(fmt.Errorf("unable to create server: %w", err))
}

// For this example, we're going to wait until a disconnect event has been
// properly handled. Set this up here.
disconnected := make(chan bool, 0)

// Setup our server handling running in a separate goroutine.
go func() {
	for true {
		ev := server.Service(10)

		switch ev.GetType() {
		case enet.EventConnect:
			fmt.Printf("[SERVER] new connection from client\n")
		case enet.EventReceive:
			fmt.Printf("[SERVER] received packet from client: %s\n", ev.GetPacket().GetData())

			// We must destroy the packet when we're done with it
			ev.GetPacket().Destroy()

			// Send back a message to the client.
			err := ev.GetPeer().SendString("message received!", 0, enet.PacketFlagReliable)
			if err != nil {
				log.Fatal(err)
			}
		case enet.EventDisconnect:
			fmt.Printf("[SERVER] client disconnected")
			close(disconnected)
		}
	}
}()

// Make a client that will speak to the server.
client, err := enet.NewHost(nil, 32, 1, 0, 0)
if err != nil {
	log.Fatal(err)
}

// Connect to the server.
peer, err := client.Connect(enet.NewAddress("localhost", port), 1, 0)
if err != nil {
	log.Fatal(err)
}

// Keep checking the client until we get a response from the server.
done := false
for !done {
	ev := client.Service(10)

	switch ev.GetType() {
	case enet.EventReceive:
		fmt.Printf("[CLIENT] received packet from server: %s\n", string(ev.GetPacket().GetData()))
		ev.GetPacket().Destroy()
		done = true
	case enet.EventNone:
		// If nothing else to do, send a packet.
		fmt.Printf("[CLIENT] sending packet to server\n")
		err = peer.SendString("hello world", 0, enet.PacketFlagReliable)
		if err != nil {
			log.Fatal(err)
		}
	}
}

// Immediately disconnect the client.
peer.DisconnectNow(0)

// Wait for the disconnection to be handled by the server.
<-disconnected

// Cleanup.
client.Destroy()
server.Destroy()
enet.Deinitialize()
Output:

enet version: 1.3.17
[SERVER] new connection from client
[CLIENT] sending packet to server
[SERVER] received packet from client: hello world
[CLIENT] received packet from server: message received!
[SERVER] client disconnected

Index

Examples

Constants

View Source
const (
	// PacketFlagReliable packets must be received by the target peer and resend attempts
	// should be made until the packet is delivered
	PacketFlagReliable PacketFlags = C.ENET_PACKET_FLAG_RELIABLE

	// PacketFlagUnsequenced packets will not be sequenced with other packets not supported
	// for reliable packets
	PacketFlagUnsequenced = C.ENET_PACKET_FLAG_UNSEQUENCED

	// PacketFlagNoAllocate packets will not allocate data, and user must supply it instead
	PacketFlagNoAllocate = C.ENET_PACKET_FLAG_NO_ALLOCATE

	// PacketFlagUnreliableFragment packets will be fragmented using unreliable (instead of
	// reliable) sends if it exceeds the MTU
	PacketFlagUnreliableFragment = C.ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT

	// PacketFlagSent specifies whether the packet has been sent from all queues it has been
	// entered into
	PacketFlagSent = C.ENET_PACKET_FLAG_SENT
)

Variables

This section is empty.

Functions

func Deinitialize

func Deinitialize()

Deinitialize enet

func Initialize

func Initialize()

Initialize enet

func LinkedVersion

func LinkedVersion() string

LinkedVersion returns the linked version of enet currently being used. Returns MAJOR.MINOR.PATCH as a string.

Types

type Address

type Address interface {
	SetHostAny()
	SetHost(ip string)
	SetPort(port uint16)

	String() string
	GetPort() uint16
}

Address specifies a portable internet address structure.

func NewAddress

func NewAddress(ip string, port uint16) Address

NewAddress creates a new address

func NewListenAddress

func NewListenAddress(port uint16) Address

NewListenAddress makes a new address ready for listening on ENET_HOST_ANY

type Event

type Event interface {
	GetType() EventType
	GetPeer() Peer
	GetChannelID() uint8
	GetData() uint32
	GetPacket() Packet
}

Event as returned by Host.Service()

type EventType

type EventType int

EventType is a type of event

const (
	// EventNone means that no event occurred within the specified time limit
	EventNone EventType = iota

	// EventConnect means that a connection request initiated by Host.Connect has completed
	// The peer field contains the peer which successfully connected
	EventConnect

	// EventDisconnect means that a peer has disconnected. This event is generated on a
	// successful completion of a disconnect initiated by Peer.Disconnect, if a peer has
	// timed out, or if a connection request intialized by Host.Connect has timed out. The
	// peer field contains the peer which disconnected. The data field contains user supplied
	// data describing the disconnection, or 0, if none is available.
	EventDisconnect

	// EventReceive means that a packet has been received from a peer. The peer field
	// specifies the peer which sent the packet. The channelID field specifies the channel
	// number upon which the packet was received. The packet field contains the packet that
	// was received; this packet must be destroyed with Packet.Destroy after use.
	EventReceive
)

type Host

type Host interface {
	Destroy()
	Service(timeout uint32) Event

	Connect(addr Address, channelCount int, data uint32) (Peer, error)

	CompressWithRangeCoder() error
	BroadcastBytes(data []byte, channel uint8, flags PacketFlags) error
	BroadcastPacket(packet Packet, channel uint8) error
	BroadcastString(str string, channel uint8, flags PacketFlags) error
	SetChecksumCRC32() error
	UsingNewPacket() error
}

Host for communicating with peers

func NewHost

func NewHost(addr Address, peerCount, channelLimit uint64, incomingBandwidth, outgoingBandwidth uint32) (Host, error)

NewHost creats a host for communicating to peers

type Packet

type Packet interface {
	Destroy()
	GetData() []byte
	GetFlags() PacketFlags
}

Packet may be sent to or received from a peer

func NewPacket

func NewPacket(data []byte, flags PacketFlags) (Packet, error)

NewPacket creates a new packet to send to peers

type PacketFlags

type PacketFlags uint32

PacketFlags are bit constants

type Peer

type Peer interface {
	GetAddress() Address

	Disconnect(data uint32)
	DisconnectNow(data uint32)
	DisconnectLater(data uint32)

	SendBytes(data []byte, channel uint8, flags PacketFlags) error
	SendString(str string, channel uint8, flags PacketFlags) error
	SendPacket(packet Packet, channel uint8) error

	// SetData sets an arbitrary value against a peer. This is useful to attach some
	// application-specific data for future use, such as an identifier.
	//
	// http://enet.bespin.org/structENetPeer.html#a1873959810db7ac7a02da90469ee384e
	//
	// Note that due to the way the enet library works, if using this you are
	// responsible for clearing this data when the peer is finished with.
	// SetData(nil) will free underlying memory and avoid any leaks.
	//
	// See http://enet.bespin.org/Tutorial.html#ManageHost for an example of this
	// in the underlying library.
	SetData(data []byte)

	// GetData returns an application-specific value that's been set
	// against this peer. This returns nil if no data has been set.
	//
	// http://enet.bespin.org/structENetPeer.html#a1873959810db7ac7a02da90469ee384e
	GetData() []byte
}

Peer is a peer which data packets may be sent or received from

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL