Güvenilir UDP Ağ İletişim Kütüphanesi
v1.3.18ENet, 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.
UDP tabanlı yapısı sayesinde TCP'ye göre çok daha düşük gecikme süresi sağlar.
UDP'nin eksik olan güvenilirlik özelliğini TCP performansını kaybetmeden sağlar.
Dinamik ve statik bant genişliği yönetimi ile ağ kaynaklarını optimize eder.
Tek bağlantı üzerinde birden fazla bağımsız veri akışı destekler.
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.
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.
// 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); }
Her kanal bağımsız olarak sıralanır, böylece bir kanaldaki paketin teslimat durumu diğer kanallardaki paketlerin teslimatını engellemez.
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.
Büyük paketler otomatik olarak uygun boyutlardaki küçük paketlere bölünür ve hedef host'ta yeniden birleştirilir.
./configure make sudo make install
# Visual Studio Developer Command Prompt'ta nmake -f Makefile.win32
#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
#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; }
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); }
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); }
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; } } }
int enet_address_get_host( const ENetAddress * address, char * hostName, size_t nameLength ); // Dönüş değerleri: // 0: başarılı // <0: hata
int enet_address_get_host_ip( const ENetAddress * address, char * hostName, size_t nameLength ); // Dönüş değerleri: // 0: başarılı // <0: hata
int enet_address_set_host( ENetAddress * address, const char * hostName ); // Dönüş değerleri: // 0: başarılı // <0: hata
int enet_address_set_host_ip( ENetAddress * address, const char * hostName ); // Dönüş değerleri: // 0: başarılı // <0: hata
void enet_deinitialize(void);
int enet_initialize(void); // Dönüş değerleri: // 0: başarılı // <0: hata
int enet_initialize_with_callbacks( ENetVersion version, const ENetCallbacks * inits ); // Dönüş değerleri: // 0: başarılı // <0: hata
ENetVersion enet_linked_version(void);
void enet_host_bandwidth_limit( ENetHost * host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth );
void enet_host_broadcast( ENetHost * host, enet_uint8 channelID, ENetPacket * packet );
void enet_host_channel_limit( ENetHost * host, size_t channelLimit );
int enet_host_check_events( ENetHost * host, ENetEvent * event ); // Dönüş değerleri: // >0: olay var // 0: olay yok // <0: hata
void enet_host_compress( ENetHost * host, const ENetCompressor * compressor );
int enet_host_compress_with_range_coder( ENetHost * host ); // Dönüş değerleri: // 0: başarılı // <0: hata
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
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
void enet_host_destroy(ENetHost * host);
void enet_host_flush(ENetHost * host);
int enet_host_service( ENetHost * host, ENetEvent * event, enet_uint32 timeout ); // Dönüş değerleri: // >0: olay var // 0: olay yok // <0: hata
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
void enet_packet_destroy(ENetPacket * packet);
int enet_packet_resize( ENetPacket * packet, size_t dataLength ); // Dönüş değerleri: // 0: başarılı // <0: hata
void enet_peer_disconnect( ENetPeer * peer, enet_uint32 data );
void enet_peer_disconnect_later( ENetPeer * peer, enet_uint32 data );
void enet_peer_disconnect_now( ENetPeer * peer, enet_uint32 data );
void enet_peer_ping(ENetPeer * peer);
void enet_peer_ping_interval( ENetPeer * peer, enet_uint32 pingInterval );
ENetPacket * enet_peer_receive( ENetPeer * peer, enet_uint8 * channelID ); // Paket varsa paket nesnesi, yoksa NULL döner
void enet_peer_reset(ENetPeer * peer);
int enet_peer_send( ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet ); // Dönüş değerleri: // 0: başarılı // <0: hata
void enet_peer_throttle_configure( ENetPeer * peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration );
void enet_peer_timeout( ENetPeer * peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum );
ENetSocket enet_socket_accept( ENetSocket socket, ENetAddress * address );
int enet_socket_bind( ENetSocket socket, const ENetAddress * address );
int enet_socket_connect( ENetSocket socket, const ENetAddress * address );
ENetSocket enet_socket_create( ENetSocketType type );
void enet_socket_destroy(ENetSocket socket);
int enet_socket_get_address( ENetSocket socket, ENetAddress * address );
int enet_socket_listen( ENetSocket socket, int backlog );
int enet_socket_receive( ENetSocket socket, ENetAddress * address, ENetBuffer * buffers, size_t bufferCount );
int enet_socket_send( ENetSocket socket, const ENetAddress * address, const ENetBuffer * buffers, size_t bufferCount );
// 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; }
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 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 oldukça taşınabilir bir kütüphanedir ve şu platformları destekler: