C Academy · Ders

Olay Döngüsü

Okunabilir yuvalara tepki verin.

3. ders / 413 adım

Olay Döngüsü, CoddyKit'te ücretsiz bir C Academy dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, C Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. C Academy kursu toplamda 4 dersten oluşur.

Sunucunun Kalbi

Olay döngüsü, epoll sunucusunu çalıştıran motordur. Hazır tanımlayıcıları tekrar tekrar bekler ve işi işleyicilere dağıtır.

Yapısı her zaman aynıdır: epoll_wait() çağrılır, döndürülen olaylar üzerinde gezinilir, her biri için işlem yapılır ve ardından döngü yeniden başlatılır. Diğer her şey bu iskelete bağlanır.

for (;;) {
    int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
    for (int i = 0; i < n; i++) handle(&events[i]);
}

epoll_wait Çağrısı

epoll_wait(); epoll tanımlayıcısını, bir epoll_event çıktı dizisini, dizinin kapasitesini ve milisaniye cinsinden bir zaman aşımını alır.

En az bir tanımlayıcı hazır olana (veya zaman aşımı dolana) kadar bekler ve dizinize kaç olayın yazıldığını döndürür. Yalnızca bu girdiler geçerlidir.

struct epoll_event events[MAX_EVENTS];
int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
if (n == -1) { perror("epoll_wait"); }

Zaman Aşımı Bağımsız Değişkeni

-1 zaman aşımı, bir olay gelene kadar süresiz bekler. 0 değeri hemen döner ve uyumadan yoklama yapar.

Pozitif bir değer, ne kadar bekleneceğini sınırlar. Bu, günlükleri boşaltmak veya boşta kalan bağlantıların süresini doldurmak gibi düzenli görevleri de çalıştırmanız gerektiğinde kullanışlıdır.

int n = epoll_wait(epfd, events, MAX_EVENTS, 1000); /* up to 1s */
if (n == 0) run_periodic_tasks();

Olay Dizisinin Boyutunu Belirleme

Dizinin kapasitesi, tek bir epoll_wait() çağrısının bildirebileceği hazır olay sayısını sınırlar. Daha fazla olay hazırsa kalanlar sonraki çağrıda döndürülür.

64 veya 1024 gibi makul bir boyut yeterlidir; epoll, bekleyen olaylar arasında çağrılar boyunca adil biçimde dönüşümlü işlem yapar, bu nedenle hiçbir olay aç kalmaz.

#define MAX_EVENTS 64
struct epoll_event events[MAX_EVENTS];

Dinleme Soketinde Dağıtım

Döngünün içinde önce hazır tanımlayıcının dinleme soketiniz olup olmadığını denetleyin. Öyleyse yeni bağlantıların beklediği anlamına gelir.

Bu bağlantıları kabul eder, engellemesiz olarak ayarlar ve epoll ile kaydedersiniz. Diğer tüm tanımlayıcılar, okunacak verisi veya yazılacak alanı olan mevcut istemcilerdir.

if (events[i].data.fd == listen_fd) {
    accept_new_connections(epfd, listen_fd);
} else {
    handle_client(epfd, &events[i]);
}

Bağlantıları Döngü İçinde Kabul Etme

Dinleme soketindeki tek bir hazır olma olayı, birden fazla bekleyen bağlantı anlamına gelebilir. EAGAIN döndürünceye kadar accept() üzerinde döngü kurun.

Bu, kenar tetiklemeli kipte zorunludur ve her durumda iyi bir uygulamadır; böylece istemcileri bir sonraki uyanmaya kadar bekletmezsiniz.

for (;;) {
    int c = accept(listen_fd, NULL, NULL);
    if (c == -1) { if (errno == EAGAIN) break; else break; }
    set_nonblocking(c);
    add_to_epoll(epfd, c);
}

Okunabilir Olayları İşleme

Bir istemcide EPOLLIN tetiklendiğinde istemciden okuyun. Seviye tetiklemeli kipte her uyanışta tek bir recv() çağrısı yapılması yeterlidir.

0 dönüşü, istemcinin bağlantıyı kapattığı anlamına gelir: gerekli temizliği yapın. EAGAIN ile birlikte negatif dönüş alınması, şimdilik kullanılabilir tüm verileri tükettiğiniz anlamına gelir.

ssize_t r = recv(fd, buf, sizeof buf, 0);
if (r == 0) { close_conn(epfd, fd); }
else if (r > 0) { process(buf, r); }

Kenar Tetiklemeli Kipte Verileri Tüketme

EPOLLET ile recv() EAGAIN döndürene kadar okumalısınız. Çekirdek sizi yalnızca okunabilir duruma geçişte bilgilendirir; bu nedenle kalan baytlar bir sonraki değişikliğe kadar kaybolur.

Okuma işlemini bir döngüye alın ve yalnızca EAGAIN veya akışın sonu durumunda döngüden çıkın.

for (;;) {
    ssize_t r = recv(fd, buf, sizeof buf, 0);
    if (r > 0) process(buf, r);
    else if (r == 0) { close_conn(epfd, fd); break; }
    else { if (errno == EAGAIN) break; else { close_conn(epfd, fd); break; } }
}

Yazılabilir Olayları İşleme

EPOLLOUT, bir soket daha fazla dışarı gönderilecek veriyi kabul edebildiğinde tetiklenir. Bunu yalnızca daha önce tamamen gönderilememiş arabelleğe alınmış baytlarınız olduğunda istersiniz.

Arabelleğinizi boşaltın; arabellek boşaldığında, sürekli yazılabilir olma bildirimleri almamak için ilgiyi yalnızca EPOLLIN olacak şekilde EPOLL_CTL_MOD ile değiştirin.

if (events[i].events & EPOLLOUT) {
    flush_pending(fd);
    if (buffer_empty(fd)) watch_read_only(epfd, fd);
}

Kesintiye Uğrayan Beklemeleri İşleme

Bir sinyal beklemeyi keserse epoll_wait(), errno == EINTR ile birlikte -1 döndürebilir. Bu gerçek bir hata değildir; yalnızca yeniden deneyin.

Sağlam döngüler EINTR durumunda devam eder ve yalnızca diğer hata kodlarını kritik kabul eder. Bunu unutmak, sunucunun sinyal aldığı ilk anda çökmesine neden olabilir.

int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
if (n == -1) {
    if (errno == EINTR) continue;
    perror("epoll_wait"); break;
}

Tek Döngü, Çok Sayıda İstemci

Hepsini bir araya getirdiğinizde tek bir iş parçacığı hazır tanımlayıcılar arasında sonsuza dek dolaşır: kabul et, oku, yaz, kapat, tekrarla.

İş parçacığı boşta kaldığında epoll_wait() içinde uyuduğu ve meşgulken yalnızca hazır işleri işlediği için bu tasarım on binlerce eşzamanlı bağlantıyı rahatça yönetir.

Kısa Denetim

Olay döngüsünü ne kadar anladığınızı sınayın.

Özet

Olay döngüsü epoll_wait() çağrısını yapar, hazır olaylar üzerinde gezinir ve işlemleri dağıtır: dinleme soketinde kabul etme, EPOLLIN durumunda okuma, EPOLLOUT durumunda arabelleği boşaltma ve kapanma durumunda temizleme.

Kabul etme ve okuma işlemlerini döngüye alın, EINTR durumunda yeniden deneyin ve EPOLLET altında verileri tamamen tüketin. Sırada eksiksiz bir yankı sunucusu oluşturacağız.

Başlamak ücretsiz

Yapay zeka eğitmeniyle C öğren — ücretsiz

Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.

Kurslar
39
Dersler
144

Sıkça Sorulan Sorular

“Olay Döngüsü” dersi ücretsiz mi?

Evet — “Olay Döngüsü” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve C Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. C Academy kursu toplamda 4 dersten oluşur.

“Olay Döngüsü” dersinde ne öğreneceğim?

Okunabilir yuvalara tepki verin. C Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

C Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te C Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.

“Olay Döngüsü” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu C Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her C Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Bloklayan ve Bloklamayan G/Ç
  2. epoll Kurulumu
  3. Olay Döngüsü
  4. Basit Bir Yankı Sunucusu
← C Academy Sayfasına Dön