Basit Bir Yankı Sunucusu
Aynı anda birçok istemciye hizmet verin.
Basit Bir Yankı Sunucusu, CoddyKit'te ücretsiz bir C Academy dersidir. Bu, 4 dersinin 4. 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.
Oluşturacağımız Şey
Bir yankı sunucusu, TCP bağlantılarını kabul eder ve istemcinin gönderdiği baytları geri yollar. Bu, ağ programlamanın "merhaba dünya" örneğidir.
Bunu epoll üzerinde oluşturacağız; böylece tek bir iş parçacığı aynı anda birçok istemciye hizmet verecek. Parçalar şunlardır: bir dinleme soketi, epoll döngüsü ve istemci başına okuma, ardından yazma işlemi.
Dinleme Soketi Oluşturma
Bir IPv4 TCP uç noktası için socket() ile başlayın. Üçlü; AF_INET, SOCK_STREAM ve 0 protokolünden oluşur.
Bu çağrı, bağlayacağımız, engellemesiz olarak işaretleyeceğimiz ve sonunda epoll ile kaydedeceğimiz bir dosya tanımlayıcısı döndürür. Her sistem çağrısında -1 durumunu denetleyin.
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd == -1) { perror("socket"); exit(1); }Adresi Yeniden Kullanma
Bağlamadan önce setsockopt() ile SO_REUSEADDR ayarını yapın. Bu, sunucunun TIME_WAIT durumunun sona ermesini beklemeden yeniden başlatılıp aynı porta yeniden bağlanmasını sağlar.
Bu ayar olmadan hızlı bir yeniden başlatma çoğunlukla EADDRINUSE hatasıyla başarısız olur; bu, geliştirme sırasında can sıkıcı bir sürprizdir.
int yes = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);Bir Porta Bağlama
Bir struct sockaddr_in yapısını aile, port ve adres bilgileriyle doldurun. Port için htons(), tüm arabirimlerde dinlemek için INADDR_ANY kullanın.
Ardından soketi bu adrese bağlamak için bind() çağrısını yapın. htons, ana bilgisayar bayt sırasını gerekli olan ağ bayt sırasına dönüştürür.
struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(8080);
bind(listen_fd, (struct sockaddr*)&addr, sizeof addr);Dinleme ve Engellemesiz Kiṕe Geçme
Soketi pasif olarak işaretlemek ve bekleyen bağlantılar için bir bekleme kuyruğu belirlemek üzere listen() çağrısını yapın. SOMAXCONN, sistemin en yüksek değerini ister.
Ardından soketi engellemesiz olarak değiştirin; böylece accept() olay döngüsünü hiçbir zaman duraklatmaz. Artık epoll ile kaydedilmeye hazırdır.
listen(listen_fd, SOMAXCONN);
set_nonblocking(listen_fd);Dinleyiciyi Kaydetme
epoll örneğini oluşturun ve dinleme soketini EPOLLIN ile ekleyin. Buradaki okunabilir olayı, kabul edilmeyi bekleyen yeni bir istemci olduğu anlamına gelir.
Tanımlayıcıyı data.fd içinde saklarız; böylece döngünün içinde dinleyiciyi tanıyabiliriz.
int epfd = epoll_create1(0);
struct epoll_event ev = { .events = EPOLLIN, .data.fd = listen_fd };
epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev);Bir İstemciyi Kabul Etme
Dinleyici okunabilir olduğunda, EAGAIN alıncaya kadar accept() üzerinde döngü kurun. Her yeni istemci soketi engellemesiz olarak ayarlanır ve EPOLLIN için kaydedilir.
Bu noktadan sonra epoll, istemci geri yankılayabileceğimiz veriler gönderdiğinde bizi bilgilendirir.
int c = accept(listen_fd, NULL, NULL);
if (c != -1) {
set_nonblocking(c);
struct epoll_event cev = { .events = EPOLLIN, .data.fd = c };
epoll_ctl(epfd, EPOLL_CTL_ADD, c, &cev);
}Yankı Mantığı
Hazır bir istemci için recv() ile bir arabelleğe okuyun. Bayt aldıysanız aynı baytları send() ile doğrudan geri gönderin.
Bu basit okuma, ardından yazma işlemi yankıdır. Gerçek kullanımda gönderilmemiş baytları arabelleğe almanız gerekir; ancak tanıtım amacıyla küçük yanıtın gönderme arabelleğine sığdığını varsayıyoruz.
char buf[4096];
ssize_t r = recv(fd, buf, sizeof buf, 0);
if (r > 0) {
send(fd, buf, r, 0);
}Bağlantı Kesilmesini Algılama
recv() çağrısının 0 döndürmesi, istemcinin düzenli bir kapatma gerçekleştirdiği anlamına gelir. EAGAIN dışındaki herhangi bir değerle birlikte negatif dönüş, gerçek bir hatadır.
Her iki durumda da tanımlayıcıyı epoll'dan kaldırın ve kaynakları serbest bırakıp başka olayları durdurmak için close() ile kapatın.
if (r == 0 || (r < 0 && errno != EAGAIN)) {
epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
close(fd);
}Eksiksiz Döngü
Parçaları birleştirin: olayları bekleyin, tanımlayıcının dinleyici mi yoksa istemci mi olduğuna göre dallanın ve uygun işlemi yapın.
Bu kısa döngü, tamamen işlevsel bir eşzamanlı yankı sunucusudur. Tek iş parçacığı, çok sayıda istemci, bağlantı başına iş parçacığı yok.
for (;;) {
int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
for (int i = 0; i < n; i++) {
if (events[i].data.fd == listen_fd) accept_clients();
else echo_or_close(events[i].data.fd);
}
}Sınama ve Sonraki Adımlar
Linux üzerinde derleyin ve nc localhost 8080 ile bağlanın; yazdığınız her şey geri gelir. Eşzamanlılığı kanıtlamak için birkaç terminal açın.
Daha sağlam hâle getirmek için: kısmi gönderimleri arabelleğe alın, EPOLLOUT durumunu işleyin, tam tüketmeyle birlikte EPOLLET kipine geçin ve bağlantının tek yönlü kapanması için EPOLLRDHUP durumunu işleyin.
Kısa Denetim
Yankı sunucusunun akışını ne kadar anladığınızı sınayın.
Özet
Bir epoll yankı sunucusu oluşturdunuz: oluşturun, SO_REUSEADDR seçeneğini ayarlayın, bağlayın, dinleyin ve engellemesiz hâle getirin. Dinleyiciyi kaydedin, bir döngüde istemcileri kabul edin ve recv()/send() ile yankılayın.
0 dönüşünü bağlantının kesilmesi olarak ele alın ve bağlantıyı düzgünce kapatın. Bu iskeletten yüksek performanslı, tek iş parçacıklı bir ağ sunucusu geliştirebilirsiniz.
Sıkça Sorulan Sorular
“Basit Bir Yankı Sunucusu” dersi ücretsiz mi?
Evet — “Basit Bir Yankı Sunucusu” 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.
“Basit Bir Yankı Sunucusu” dersinde ne öğreneceğim?
Aynı anda birçok istemciye hizmet 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 4. dersidir.
“Basit Bir Yankı Sunucusu” 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
- Bloklayan ve Bloklamayan G/Ç
- epoll Kurulumu
- Olay Döngüsü
- Basit Bir Yankı Sunucusu