A reliable UDP networking layer for C++
ENet is a simple and robust network communication layer on top of UDP (User Datagram Protocol). It provides an interface for reliable, in-order delivery of packets, making it highly suitable for games and real-time applications where standard TCP may introduce unacceptable latency due to head-of-line blocking.
Key Features:
To use ENet, include the main header file in your source code and link against the ENet library.
#include <enet/enet.h>
#include <iostream>
Note: On Linux, link with -lenet. On Windows, link with enet.lib (or
enet64.lib), ws2_32.lib, and winmm.lib.
You must initialize the ENet library before you can use it, and deinitialize it before your program exits.
if (enet_initialize() != 0) {
std::cerr << "An error occurred while initializing ENet.\n";
return 1;
}
atexit(enet_deinitialize);
Connections are managed by hosts. A server binds to a specific port, while a client usually lets the OS assign a port.
ENetAddress address;
ENetHost* server;
// Bind the server to the default localhost and port 1234
address.host = ENET_HOST_ANY;
address.port = 1234;
server = enet_host_create(&address,
32, // allow up to 32 clients and/or outgoing connections
2, // allow up to 2 channels to be used, 0 and 1
0, // assume any amount of incoming bandwidth
0); // assume any amount of outgoing bandwidth
if (server == nullptr) {
std::cerr << "An error occurred while trying to create an ENet server host.\n";
exit(1);
}
ENetHost* client;
client = enet_host_create(nullptr, // create a client host
1, // only allow 1 outgoing connection
2, // allow up 2 channels to be used, 0 and 1
0, // assume any amount of incoming bandwidth
0); // assume any amount of outgoing bandwidth
if (client == nullptr) {
std::cerr << "An error occurred while trying to create an ENet client host.\n";
exit(1);
}
A client initiates a connection to a server using the enet_host_connect function.
ENetAddress address;
ENetEvent event;
ENetPeer* peer;
// Connect to localhost:1234
enet_address_set_host(&address, "127.0.0.1");
address.port = 1234;
peer = enet_host_connect(client, &address, 2, 0);
if (peer == nullptr) {
std::cerr << "No available peers for initiating an ENet connection.\n";
exit(1);
}
// Wait up to 5 seconds for the connection attempt to succeed.
if (enet_host_service(client, &event, 5000) > 0 &&
event.type == ENET_EVENT_TYPE_CONNECT) {
std::cout << "Connection to 127.0.0.1:1234 succeeded.\n";
} else {
enet_peer_reset(peer);
std::cout << "Connection to 127.0.0.1:1234 failed.\n";
}
ENet operates primarily through an event loop. You process incoming datagrams and events by calling
enet_host_service.
ENetEvent event;
// Poll for network events
while (enet_host_service(server, &event, 1000) > 0) {
switch (event.type) {
case ENET_EVENT_TYPE_CONNECT:
std::cout << "A new client connected from "
<< std::hex << event.peer->address.host << std::dec
<< ":" << event.peer->address.port << "\n";
break;
case ENET_EVENT_TYPE_RECEIVE:
std::cout << "A packet of length " << event.packet->dataLength
<< " was received on channel " << (int)event.channelID << ".\n";
// Clean up the packet now that we're done using it.
enet_packet_destroy(event.packet);
break;
case ENET_EVENT_TYPE_DISCONNECT:
std::cout << "Client disconnected.\n";
break;
case ENET_EVENT_TYPE_NONE:
break;
}
}
You can send reliable or unreliable packets over specific channels.
// Create a reliable packet
std::string message = "Hello Server!";
ENetPacket* packet = enet_packet_create(message.c_str(),
message.length() + 1,
ENET_PACKET_FLAG_RELIABLE);
// Send the packet to the peer over channel 0
enet_peer_send(peer, 0, packet);
// Optionally flush the buffers to send the packet immediately
// enet_host_flush(host);
Bandwidth Limitation: Determine how much bandwidth the ENet host may use.
// limit incoming to 512Kbps and outgoing to 256Kbps
enet_host_bandwidth_limit(server, 512 * 1024, 256 * 1024);
Latency/Ping: ENet automatically measures the round trip time of the connection.
std::cout << "Current ping to peer: " << peer->roundTripTime << " ms\n";
The following example demonstrates a basic server and client interacting to form a chat room using Modern C++.
#include <enet/enet.h>
#include <iostream>
#include <string>
int main() {
if (enet_initialize() != 0) return 1;
ENetAddress address;
address.host = ENET_HOST_ANY;
address.port = 1234;
ENetHost* server = enet_host_create(&address, 32, 2, 0, 0);
if (!server) return 1;
std::cout << "Server listening on port 1234...\n";
ENetEvent event;
while (true) {
while (enet_host_service(server, &event, 1000) > 0) {
if (event.type == ENET_EVENT_TYPE_CONNECT) {
std::cout << "User connected.\n";
} else if (event.type == ENET_EVENT_TYPE_RECEIVE) {
std::string msg(reinterpret_cast<char*>(event.packet->data), event.packet->dataLength);
std::cout << "Received message: " << msg << "\n";
// Broadcast to everyone
ENetPacket* broadcastPacket = enet_packet_create(
event.packet->data, event.packet->dataLength, ENET_PACKET_FLAG_RELIABLE);
enet_host_broadcast(server, 0, broadcastPacket);
enet_packet_destroy(event.packet);
} else if (event.type == ENET_EVENT_TYPE_DISCONNECT) {
std::cout << "User disconnected.\n";
}
}
}
enet_host_destroy(server);
enet_deinitialize();
return 0;
}
#include <enet/enet.h>
#include <iostream>
#include <string>
#include <thread>
#include <atomic>
std::atomic<bool> running(true);
void receive_thread(ENetHost* client) {
ENetEvent event;
while (running) {
while (enet_host_service(client, &event, 10) > 0) {
if (event.type == ENET_EVENT_TYPE_RECEIVE) {
std::string msg(reinterpret_cast<char*>(event.packet->data), event.packet->dataLength);
std::cout << "\nIncoming: " << msg << "\n> " << std::flush;
enet_packet_destroy(event.packet);
}
}
}
}
int main() {
if (enet_initialize() != 0) return 1;
ENetHost* client = enet_host_create(nullptr, 1, 2, 0, 0);
ENetAddress address;
enet_address_set_host(&address, "127.0.0.1");
address.port = 1234;
ENetPeer* peer = enet_host_connect(client, &address, 2, 0);
ENetEvent event;
if (enet_host_service(client, &event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) {
std::cout << "Connected. Type '/quit' to exit.\n";
} else {
std::cout << "Failed to connect.\n";
return 1;
}
// Start receiving thread
std::thread rx(receive_thread, client);
std::string input;
while (true) {
std::cout << "> ";
std::getline(std::cin, input);
if (input == "/quit") {
running = false;
break;
}
ENetPacket* packet = enet_packet_create(input.c_str(), input.length() + 1, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(peer, 0, packet);
}
rx.join();
enet_peer_disconnect(peer, 0);
enet_host_flush(client);
return 0;
}
© ENet Beginners Documentation Project.