Skip to content

Instantly share code, notes, and snippets.

@tuket
Created November 17, 2022 15:36
Show Gist options
  • Save tuket/b2814c3f3c4d977525d1a8143ecd390e to your computer and use it in GitHub Desktop.
Save tuket/b2814c3f3c4d977525d1a8143ecd390e to your computer and use it in GitHub Desktop.
Simple ENet example
#include <stdio.h>
#include <thread>
#include "enet.h"
const uint16_t THE_PORT = 55555;
static void sendString(ENetPeer* peer, const char* str)
{
ENetPacket* packet = enet_packet_create(str, strlen(str) + 1, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(peer, 0, packet);
}
void server_fn()
{
ENetHost* host = nullptr;
ENetPeer* peer = nullptr;
const ENetAddress addr = { ENET_HOST_ANY, THE_PORT };
host = enet_host_create(&addr, 1, 1, 0, 0);
assert(host != nullptr);
bool done = false;
while (!done) { // server loop
ENetEvent event;
const int serviceRet = enet_host_service(host, &event, 1);
if (serviceRet <= 0)
continue;
switch (event.type)
{
case ENET_EVENT_TYPE_CONNECT: {
printf("[SERVER] Connected!\n");
peer = event.peer;
} break;
case ENET_EVENT_TYPE_RECEIVE: {
printf("[SERVER] Received a message: %s\n", (const char*)event.packet->data);
enet_packet_destroy(event.packet);
sendString(peer, "Me too!");
enet_host_flush(host); // since we are going to disconnect right after, we need to do this flush. Otherwise, the message won't get to the other peer
printf("[SERVER] Now I want to disconnect\n");
enet_peer_disconnect(peer, 0);
} break;
case ENET_EVENT_TYPE_DISCONNECT: {
printf("[SERVER] Client acknowledged disconnection\n");
done = true;
} break;
}
}
}
void client_fn()
{
ENetHost* host;
ENetPeer* peer;
host = enet_host_create(nullptr, 1, 1, 0, 0);
assert(host != nullptr);
const ENetAddress addr = { enet_v6_localhost, THE_PORT };
peer = enet_host_connect(host, &addr, 1, 0);
printf("[CLIENT] Attempting to connect to the server...\n");
bool done = false;
while(!done) { // client loop
ENetEvent event;
const int serviceRet = enet_host_service(host, &event, 1);
if (serviceRet <= 0)
continue;
switch (event.type)
{
case ENET_EVENT_TYPE_CONNECT: {
printf("[CLIENT] Connected!\n");
const char* msg = "I love ENet";
sendString(peer, msg);
} break;
case ENET_EVENT_TYPE_RECEIVE: {
printf("[CLIENT] Received a message: %s\n", (const char*)event.packet->data);
enet_packet_destroy(event.packet);
} break;
case ENET_EVENT_TYPE_DISCONNECT: {
printf("[CLIENT] Looks like the server wants to disconnect\n");
done = true;
} break;
}
}
}
int main()
{
printf("START!\n");
enet_initialize();
std::thread serverThread(server_fn);
std::thread clientThread(client_fn);
serverThread.join();
clientThread.join();
printf("END!\n");
}
@tuket
Copy link
Author

tuket commented Nov 17, 2022

This other example is similar but parses cmd line args to allow decoupling client/server execution:

#include <stdio.h>
#include <thread>
#include "enet.h"

const uint16_t THE_PORT = 55555;

static void sendString(ENetPeer* peer, const char* str)
{
	ENetPacket* packet = enet_packet_create(str, strlen(str) + 1, ENET_PACKET_FLAG_RELIABLE);
	enet_peer_send(peer, 0, packet);
}

void server_fn()
{
	ENetHost* host = nullptr;
	ENetPeer* peer = nullptr;

	const ENetAddress addr = { ENET_HOST_ANY, THE_PORT };
	host = enet_host_create(&addr, 1, 1, 0, 0);
	assert(host != nullptr);

	bool done = false;
	while (!done) { // server loop
		ENetEvent event;
		const int serviceRet = enet_host_service(host, &event, 1);
		if (serviceRet <= 0)
			continue;

		switch (event.type)
		{
		case ENET_EVENT_TYPE_CONNECT: {
			printf("[SERVER] Connected!\n");
			peer = event.peer;
		} break;

		case ENET_EVENT_TYPE_RECEIVE: {
			printf("[SERVER] Received a message: %s\n", (const char*)event.packet->data);
			enet_packet_destroy(event.packet);

			sendString(peer, "Me too!");
			enet_host_flush(host); // since we are going to disconnect right after, we need to do this flush. Otherwise, the message won't get to the destination

			printf("[SERVER] Now I want to disconnect\n");
			enet_peer_disconnect(peer, 0);
		} break;

		case ENET_EVENT_TYPE_DISCONNECT: {
			printf("[SERVER] Client acknowledged disconnection\n");
			done = true;
		} break;
		}
	}
}

void client_fn()
{
	ENetHost* host;
	ENetPeer* peer;

	host = enet_host_create(nullptr, 1, 1, 0, 0);
	assert(host != nullptr);

	const ENetAddress addr = { enet_v6_localhost, THE_PORT };
	peer = enet_host_connect(host, &addr, 1, 0);
	printf("[CLIENT] Attempting to connect to the server...\n");

	bool done = false;
	while(!done) { // client loop
		ENetEvent event;
		const int serviceRet = enet_host_service(host, &event, 1);
		if (serviceRet <= 0)
			continue;

		switch (event.type)
		{
		case ENET_EVENT_TYPE_CONNECT: {
			printf("[CLIENT] Connected!\n");
			const char* msg = "I love ENet";
			sendString(peer, msg);
		} break;

		case ENET_EVENT_TYPE_RECEIVE: {
			printf("[CLIENT] Received a message: %s\n", (const char*)event.packet->data);
			enet_packet_destroy(event.packet);
		} break;

		case ENET_EVENT_TYPE_DISCONNECT: {
			printf("[CLIENT] Looks like the server wants to disconnect\n");
			done = true;
		} break;
		}
	}
}

int main(int argc, char** argv)
{
	bool launchServer = false;
	bool launchClient = false;
	for (int i = 1; i < argc; i++) {
		if (strcmp(argv[i], "server"))
			launchServer = true;
		if (strcmp(argv[i], "client"))
			launchClient = true;
	}
	if (!launchServer && !launchClient)
		launchServer = launchClient = true;

	printf("START!\n");
	enet_initialize();

	std::thread serverThread, clientThread;
	
	if(launchServer)
		serverThread = std::thread(server_fn);
	if(launchClient)
		clientThread = std::thread(client_fn);

	if(launchServer)
		serverThread.join();
	if(launchClient)
		clientThread.join();

	printf("END!\n");
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment