ENet Kütüphanesi

Güvenilir UDP Ağ İletişim Kütüphanesi

v1.3.18

ENet Nedir?

ENet, UDP (User Datagram Protocol) üzerine kurulmuş, nispeten ince, basit ve sağlam bir ağ iletişim katmanı sağlamayı amaçlayan bir kütüphanedir. Temel özelliği, paketlerin isteğe bağlı güvenilir ve sıralı teslimatını sağlamasıdır.

Önemli: ENet, kimlik doğrulama, lobi sistemi, sunucu keşfi, şifreleme gibi üst düzey ağ özelliklerini içermez. Bu sayede kütüphane esnek, taşınabilir ve kolayca entegre edilebilir kalır.

Neden ENet?

Düşük Gecikme

UDP tabanlı yapısı sayesinde TCP'ye göre çok daha düşük gecikme süresi sağlar.

Güvenilir İletim

UDP'nin eksik olan güvenilirlik özelliğini TCP performansını kaybetmeden sağlar.

Bant Genişliği Yönetimi

Dinamik ve statik bant genişliği yönetimi ile ağ kaynaklarını optimize eder.

Çoklu Kanal

Tek bağlantı üzerinde birden fazla bağımsız veri akışı destekler.

ENet Özellikleri

Bağlantı Yönetimi

ENet, yabancı bir host ile iletişim kurmak için basit bir bağlantı arayüzü sağlar. Bağlantının canlılığı sık aralıklarla ping gönderilerek aktif olarak izlenir.

Paket Sıralama

ENet, gönderilen her pakete artan bir sıra numarası atayarak tüm paketler için sıralama sağlar. Düşük sıra numaralı bir paket, yüksek sıra numaralı paketten önce teslim edilir.

Paket Sıralama Örneği
// Güvenilir paket için sıralama garantisi
if (paket_numarası > beklenen_numara) {
    // Önceki paketler gelene kadar bekle
    bekletme_kuyruğuna_ekle(paket);
} else {
    // Paketi hemen işle
    paketi_işle(paket);
}
                

Çoklu Kanal Desteği

Her kanal bağımsız olarak sıralanır, böylece bir kanaldaki paketin teslimat durumu diğer kanallardaki paketlerin teslimatını engellemez.

Güvenirlik

ENet, yabancı host'un tüm güvenilir paketlerin alındığını onaylamasını sağlayarak isteğe bağlı paket teslim güvenilirliği sağlar.

Fragmentasyon

Büyük paketler otomatik olarak uygun boyutlardaki küçük paketlere bölünür ve hedef host'ta yeniden birleştirilir.

Kurulum

Gereksinimler

Derleme

Linux/Unix
./configure
make
sudo make install
                
Windows (Visual Studio)
# Visual Studio Developer Command Prompt'ta
nmake -f Makefile.win32
                

Projenize Dahil Etme

C/C++ Include
#include <enet/enet.h>

// Not: enet.h dosyasını dizin ön eki olmadan include etmeyin
// Bu bazı sistemlerde dosya adı çakışmalarına neden olabilir
                

Başlangıç Öğreticisi

1. Kütüphane Başlatma

Başlatma ve Sonlandırma
#include <enet/enet.h>

int main() {
    // ENet kütüphanesini başlat
    if (enet_initialize() != 0) {
        fprintf(stderr, "ENet başlatma hatası!\n");
        return EXIT_FAILURE;
    }
    
    // Program çıkışında temizlik yap
    atexit(enet_deinitialize);
    
    return 0;
}
                

2. Sunucu Oluşturma

Sunucu Host Oluşturma
ENetAddress adres;
ENetHost * sunucu;

// Sunucu adresini ayarla
adres.host = ENET_HOST_ANY;
adres.port = 1234;

// Sunucu oluştur
// Parametreler: adres, max bağlantı, kanal sayısı, gelen/giden bant genişliği
sunucu = enet_host_create(&adres, 32, 2, 0, 0);

if (sunucu == NULL) {
    fprintf(stderr, "Sunucu oluşturma hatası!\n");
    exit(EXIT_FAILURE);
}
                

3. İstemci Oluşturma

İstemci Host Oluşturma
ENetHost * istemci;
ENetAddress adres;
ENetPeer * peer;

// İstemci oluştur (adres belirtilmez)
istemci = enet_host_create(NULL, 1, 2, 0, 0);

if (istemci == NULL) {
    fprintf(stderr, "İstemci oluşturma hatası!\n");
    exit(EXIT_FAILURE);
}

// Sunucuya bağlan
enet_address_set_host(&adres, "localhost");
adres.port = 1234;

peer = enet_host_connect(istemci, &adres, 2, 0);

if (peer == NULL) {
    fprintf(stderr, "Bağlantı başlatma hatası!\n");
    exit(EXIT_FAILURE);
}
                

4. Olay İşleme

Olay Döngüsü
ENetEvent olay;

while (1) {
    // Olayları kontrol et (5 saniye timeout)
    while (enet_host_service(sunucu, &olay, 5000) > 0) {
        switch (olay.type) {
            case ENET_EVENT_TYPE_CONNECT:
                printf("Yeni bağlantı: %x:%u\n", 
                       olay.peer->address.host,
                       olay.peer->address.port);
                olay.peer->data = "İstemci Bilgisi";
                break;
                
            case ENET_EVENT_TYPE_RECEIVE:
                printf("Paket alındı: '%s' (Kanal %u)\n",
                       olay.packet->data, olay.channelID);
                enet_packet_destroy(olay.packet);
                break;
                
            case ENET_EVENT_TYPE_DISCONNECT:
                printf("Bağlantı kesildi: %s\n", olay.peer->data);
                olay.peer->data = NULL;
                break;
        }
    }
}
                

Tüm Fonksiyonlar

Adres Fonksiyonları

enet_address_get_host
Belirtilen adres için ters DNS araması yapar.
	int enet_address_get_host(
		const ENetAddress * address,
		char * hostName,
		size_t nameLength
	);

	// Dönüş değerleri:
	//   0: başarılı
	//   <0: hata
							
enet_address_get_host_ip
Adresin IP'sini insan tarafından okunabilir formatta döndürür.
	int enet_address_get_host_ip(
		const ENetAddress * address,
		char * hostName,
		size_t nameLength
	);

	// Dönüş değerleri:
	//   0: başarılı
	//   <0: hata
							
enet_address_set_host
Host ismini çözerek adres yapısını doldurur.
	int enet_address_set_host(
		ENetAddress * address,
		const char * hostName
	);

	// Dönüş değerleri:
	//   0: başarılı
	//   <0: hata
							
enet_address_set_host_ip
IP adresini ayrıştırarak adres yapısını doldurur.
	int enet_address_set_host_ip(
		ENetAddress * address,
		const char * hostName
	);

	// Dönüş değerleri:
	//   0: başarılı
	//   <0: hata
							

Global Fonksiyonlar

enet_deinitialize
ENet kütüphanesini kapatır ve kaynakları serbest bırakır.
	void enet_deinitialize(void);
							
enet_initialize
ENet kütüphanesini başlatır.
	int enet_initialize(void);

	// Dönüş değerleri:
	//   0: başarılı
	//   <0: hata
							
enet_initialize_with_callbacks
Özel geri çağrılarla ENet kütüphanesini başlatır.
	int enet_initialize_with_callbacks(
		ENetVersion version,
		const ENetCallbacks * inits
	);

	// Dönüş değerleri:
	//   0: başarılı
	//   <0: hata
							
enet_linked_version
Bağlı ENet kütüphanesinin sürüm numarasını döndürür.
	ENetVersion enet_linked_version(void);
							

Host Fonksiyonları

enet_host_bandwidth_limit
Host'un bant genişliği sınırlarını ayarlar.
	void enet_host_bandwidth_limit(
		ENetHost * host,
		enet_uint32 incomingBandwidth,
		enet_uint32 outgoingBandwidth
	);
							
enet_host_broadcast
Tüm bağlı peer'lere paket gönderir.
	void enet_host_broadcast(
		ENetHost * host,
		enet_uint8 channelID,
		ENetPacket * packet
	);
							
enet_host_channel_limit
Host'un kanal sınırını ayarlar.
	void enet_host_channel_limit(
		ENetHost * host,
		size_t channelLimit
	);
							
enet_host_check_events
Host'ta bekleyen olayları kontrol eder.
	int enet_host_check_events(
		ENetHost * host,
		ENetEvent * event
	);

	// Dönüş değerleri:
	//   >0: olay var
	//   0: olay yok
	//   <0: hata
							
enet_host_compress
Host için paket sıkıştırıcı ayarlar.
	void enet_host_compress(
		ENetHost * host,
		const ENetCompressor * compressor
	);
							
enet_host_compress_with_range_coder
Varsayılan aralık kodlayıcı ile sıkıştırmayı etkinleştirir.
	int enet_host_compress_with_range_coder(
		ENetHost * host
	);

	// Dönüş değerleri:
	//   0: başarılı
	//   <0: hata
							
enet_host_connect
Uzak bir host'a bağlantı başlatır.
	ENetPeer * enet_host_connect(
		ENetHost * host,
		const ENetAddress * address,
		size_t channelCount,
		enet_uint32 data
	);

	// Başarılıysa peer nesnesi, başarısızsa NULL döner
							
enet_host_create
Yeni bir host oluşturur (sunucu veya istemci).
	ENetHost * enet_host_create(
		const ENetAddress * address,
		size_t peerCount,
		size_t channelLimit,
		enet_uint32 incomingBandwidth,
		enet_uint32 outgoingBandwidth
	);

	// Başarılıysa host nesnesi, başarısızsa NULL döner
							
enet_host_destroy
Host'u ve tüm kaynaklarını yok eder.
	void enet_host_destroy(ENetHost * host);
							
enet_host_flush
Tüm sıralanmış paketleri gönderir.
	void enet_host_flush(ENetHost * host);
							
enet_host_service
Host olaylarını belirtilen süre boyunca işler.
	int enet_host_service(
		ENetHost * host,
		ENetEvent * event,
		enet_uint32 timeout
	);

	// Dönüş değerleri:
	//   >0: olay var
	//   0: olay yok
	//   <0: hata
							

Paket Fonksiyonları

enet_packet_create
Yeni bir ağ paketi oluşturur.
	ENetPacket * enet_packet_create(
		const void * data,
		size_t dataLength,
		enet_uint32 flags
	);

	// Flags:
	//   ENET_PACKET_FLAG_RELIABLE: Güvenilir teslimat
	//   ENET_PACKET_FLAG_UNSEQUENCED: Sırasız teslimat
	//   ENET_PACKET_FLAG_NO_ALLOCATE: Bellek kopyalamadan kullan
							
enet_packet_destroy
Paketi ve verisini yok eder.
	void enet_packet_destroy(ENetPacket * packet);
							
enet_packet_resize
Paketin boyutunu yeniden ayarlar.
	int enet_packet_resize(
		ENetPacket * packet,
		size_t dataLength
	);

	// Dönüş değerleri:
	//   0: başarılı
	//   <0: hata
							

Peer Fonksiyonları

enet_peer_disconnect
Peer ile bağlantıyı kapatmayı talep eder.
	void enet_peer_disconnect(
		ENetPeer * peer,
		enet_uint32 data
	);
							
enet_peer_disconnect_later
Tüm paketler gönderildikten sonra bağlantıyı kapatır.
	void enet_peer_disconnect_later(
		ENetPeer * peer,
		enet_uint32 data
	);
							
enet_peer_disconnect_now
Peer ile bağlantıyı hemen koparır.
	void enet_peer_disconnect_now(
		ENetPeer * peer,
		enet_uint32 data
	);
							
enet_peer_ping
Peer'a ping isteği gönderir.
	void enet_peer_ping(ENetPeer * peer);
							
enet_peer_ping_interval
Ping aralığını ayarlar.
	void enet_peer_ping_interval(
		ENetPeer * peer,
		enet_uint32 pingInterval
	);
							
enet_peer_receive
Peer'dan gelen paketleri alır.
	ENetPacket * enet_peer_receive(
		ENetPeer * peer,
		enet_uint8 * channelID
	);

	// Paket varsa paket nesnesi, yoksa NULL döner
							
enet_peer_reset
Peer'ı sıfırlar ve bağlantıyı hemen keser.
	void enet_peer_reset(ENetPeer * peer);
							
enet_peer_send
Peer'a paket gönderir.
	int enet_peer_send(
		ENetPeer * peer,
		enet_uint8 channelID,
		ENetPacket * packet
	);

	// Dönüş değerleri:
	//   0: başarılı
	//   <0: hata
							
enet_peer_throttle_configure
Peer'ın trafik kontrol parametrelerini ayarlar.
	void enet_peer_throttle_configure(
		ENetPeer * peer,
		enet_uint32 interval,
		enet_uint32 acceleration,
		enet_uint32 deceleration
	);
							
enet_peer_timeout
Peer zaman aşımı parametrelerini ayarlar.
	void enet_peer_timeout(
		ENetPeer * peer,
		enet_uint32 timeoutLimit,
		enet_uint32 timeoutMinimum,
		enet_uint32 timeoutMaximum
	);
							

Soket Fonksiyonları

enet_socket_accept
Gelen bağlantı isteklerini kabul eder.
	ENetSocket enet_socket_accept(
		ENetSocket socket,
		ENetAddress * address
	);
							
enet_socket_bind
Soketi belirli bir adrese bağlar.
	int enet_socket_bind(
		ENetSocket socket,
		const ENetAddress * address
	);
							
enet_socket_connect
Soketi uzak adrese bağlar.
	int enet_socket_connect(
		ENetSocket socket,
		const ENetAddress * address
	);
							
enet_socket_create
Yeni bir soket oluşturur.
	ENetSocket enet_socket_create(
		ENetSocketType type
	);
							
enet_socket_destroy
Soketi kapatır ve kaynakları serbest bırakır.
	void enet_socket_destroy(ENetSocket socket);
							
enet_socket_get_address
Soketin bağlı olduğu adresi alır.
	int enet_socket_get_address(
		ENetSocket socket,
		ENetAddress * address
	);
							
enet_socket_listen
Soketi dinleme moduna alır.
	int enet_socket_listen(
		ENetSocket socket,
		int backlog
	);
							
enet_socket_receive
Soketten veri alır.
	int enet_socket_receive(
		ENetSocket socket,
		ENetAddress * address,
		ENetBuffer * buffers,
		size_t bufferCount
	);
							
enet_socket_send
Sokete veri gönderir.
	int enet_socket_send(
		ENetSocket socket,
		const ENetAddress * address,
		const ENetBuffer * buffers,
		size_t bufferCount
	);
							

Örnek Kodlar

Temel İstemci-Sunucu Örneği

Sunucu Örneği
// Basit bir ENet sunucusu
#include <stdio.h>
#include <stdlib.h>
#include <enet/enet.h>

int main(int argc, char * argv[]) {
    ENetHost * server;
    ENetAddress address;
    ENetEvent event;
    int eventStatus;

    // ENet başlat
    if (enet_initialize() != 0) {
        fprintf(stderr, "ENet başlatılamadı.\n");
        return EXIT_FAILURE;
    }
    atexit(enet_deinitialize);

    // Sunucu adresini ayarla
    address.host = ENET_HOST_ANY;
    address.port = 1234;

    // Sunucu oluştur
    server = enet_host_create(&address, 32, 2, 0, 0);

    if (server == NULL) {
        fprintf(stderr, "Sunucu oluşturulamadı.\n");
        return EXIT_FAILURE;
    }

    printf("Sunucu çalışıyor (port: %d)...\n", address.port);

    // Ana döngü
    while (1) {
        eventStatus = enet_host_service(server, &event, 1000);

        // Olay yoksa devam et
        if (eventStatus <= 0) continue;

        switch (event.type) {
            case ENET_EVENT_TYPE_CONNECT:
                printf("Yeni bağlantı: %x:%u\n", 
                    event.peer->address.host, 
                    event.peer->address.port);
                break;

            case ENET_EVENT_TYPE_RECEIVE:
                printf("Paket alındı: %s\n", event.packet->data);
                enet_packet_destroy(event.packet);
                break;

            case ENET_EVENT_TYPE_DISCONNECT:
                printf("Bağlantı kesildi.\n");
                event.peer->data = NULL;
                break;
        }
    }

    enet_host_destroy(server);
    return EXIT_SUCCESS;
}
                

Sıkça Sorulan Sorular

ENet TCP'den neden daha iyi?

ENet, UDP üzerine inşa edilmiş bir kütüphane olması nedeniyle TCP'nin getirdiği bazı kısıtlamalardan kurtulur. Özellikle düşük gecikme gerektiren uygulamalarda (oyunlar, gerçek zamanlı sistemler) TCP'ye göre önemli avantajlar sağlar. Ayrıca, ENet'in güvenilir ve güvenilmez paketleri karıştırabilme özelliği, farklı veri türleri için esneklik sağlar.

ENet güvenli mi?

ENet temel olarak şifreleme veya kimlik doğrulama sağlamaz. Bu nedenle güvenlik için ek katmanlara ihtiyaç duyulur. Uygulama geliştiriciler, güvenli iletişim için DTLS gibi protokollerle ENet'i birlikte kullanabilir veya uygulama katmanında şifreleme uygulayabilirler.

ENet hangi platformları destekler?

ENet oldukça taşınabilir bir kütüphanedir ve şu platformları destekler: