C Academy · पाठ

Event Loop

पढ़े जा सकने वाले Sockets पर प्रतिक्रिया दें।

पाठ 3, कुल 4 में से13 चरण

Event Loop, CoddyKit पर C Academy का एक निःशुल्क पाठ है। यह 4 में से 3वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह C Academy सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। C Academy पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

सर्वर का केंद्र

इवेंट लूप वह इंजन है जो epoll सर्वर को चलाता है। यह तैयार वर्णनकर्ताओं के लिए बार-बार प्रतीक्षा करता है और काम को हैंडलरों को सौंपता है।

इसका ढाँचा हमेशा एक जैसा होता है: epoll_wait() कॉल करें, लौटाए गए इवेंट पर क्रम से जाएँ, हर एक पर कार्य करें, फिर दोबारा लूप चलाएँ। बाकी सब इसी ढाँचे पर निर्भर करता है।

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

epoll_wait को कॉल करना

epoll_wait() epoll fd, epoll_event की एक आउटपुट ऐरे, उसकी क्षमता और मिलीसेकंड में एक टाइमआउट लेता है।

यह तब तक रुकता है जब तक कम-से-कम एक वर्णनकर्ता तैयार न हो जाए या टाइमआउट समाप्त न हो जाए, और लौटाता है कि आपकी ऐरे में कितने इवेंट भरे गए। केवल वही प्रविष्टियाँ मान्य होती हैं।

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

टाइमआउट आर्ग्युमेंट

-1 का टाइमआउट किसी इवेंट के आने तक अनिश्चित समय के लिए रुकता है। 0 का मान तुरंत लौटता है और बिना सोए जाँच करता है।

धनात्मक मान प्रतीक्षा की अधिकतम अवधि तय करता है, जो तब उपयोगी है जब आपको लॉग दर्ज करने या निष्क्रिय कनेक्शन की अवधि समाप्त करने जैसे आवधिक कार्य भी चलाने हों।

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

इवेंट ऐरे का आकार तय करना

ऐरे की क्षमता यह सीमा तय करती है कि एक epoll_wait() कॉल कितने तैयार इवेंट रिपोर्ट कर सकती है। यदि इससे अधिक इवेंट तैयार हों, तो बाकी अगली कॉल में लौटाए जाते हैं।

64 या 1024 जैसा मध्यम आकार पर्याप्त है; epoll अलग-अलग कॉल में लंबित इवेंट को निष्पक्ष रूप से बारी-बारी से लौटाता है, इसलिए कोई इवेंट भूखा नहीं रहता।

#define MAX_EVENTS 64
struct epoll_event events[MAX_EVENTS];

सुनने वाले सॉकेट पर कार्य सौंपना

लूप के भीतर पहले जाँचें कि तैयार वर्णनकर्ता आपका सुनने वाला सॉकेट है या नहीं। यदि ऐसा है, तो इसका अर्थ है कि नए कनेक्शन प्रतीक्षा कर रहे हैं।

आप उन्हें स्वीकार करते हैं, उन्हें नॉन-ब्लॉकिंग बनाते हैं और epoll में पंजीकृत करते हैं। बाकी सभी वर्णनकर्ता मौजूदा क्लाइंट होते हैं, जिनके पास पढ़ने के लिए डेटा या लिखने के लिए जगह होती है।

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

लूप में कनेक्शन स्वीकार करना

सुनने वाले सॉकेट पर एक तैयारी इवेंट का अर्थ कई लंबित कनेक्शन हो सकता है। accept() को तब तक लूप में चलाएँ जब तक वह EAGAIN न लौटाए।

एज-ट्रिगर्ड मोड में यह आवश्यक है और हर जगह अच्छी पद्धति भी है, ताकि क्लाइंट को अगली बार सक्रिय होने तक प्रतीक्षा न करनी पड़े।

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);
}

पढ़ने योग्य इवेंट संभालना

जब किसी क्लाइंट पर EPOLLIN सक्रिय हो, तो उससे पढ़ें। लेवल-ट्रिगर्ड मोड में हर बार सक्रिय होने पर एक recv() करना पर्याप्त है।

0 का लौटना बताता है कि क्लाइंट ने कनेक्शन बंद कर दिया है: उसकी सफ़ाई करें। EAGAIN के साथ ऋणात्मक परिणाम का अर्थ है कि फिलहाल उपलब्ध सारा डेटा पढ़ लिया गया है।

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

एज-ट्रिगर्ड मोड में डेटा खाली करना

EPOLLET के साथ आपको तब तक पढ़ना होगा जब तक recv() EAGAIN न लौटाए। कर्नेल आपको केवल पढ़ने योग्य बनने की स्थिति में बदलाव पर सूचना देता है, इसलिए बचे हुए बाइट अगला बदलाव होने तक खोए हुए लगेंगे।

पढ़ने की प्रक्रिया को एक लूप में रखें और केवल EAGAIN या स्ट्रीम के अंत पर उससे बाहर निकलें।

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; } }
}

लिखने योग्य इवेंट संभालना

EPOLLOUT तब सक्रिय होता है जब सॉकेट अधिक बाहर जाने वाला डेटा स्वीकार कर सकता है। आप इसे केवल तब चाहते हैं जब आपके पास ऐसे बफ़र किए हुए बाइट हों जिन्हें पहले पूरी तरह भेजा नहीं जा सका।

अपने बफ़र को खाली करें; उसके खाली हो जाने पर रुचि को केवल EPOLLIN पर वापस बदलने के लिए EPOLL_CTL_MOD का उपयोग करें, ताकि लगातार लिखने-योग्य सूचनाओं की बाढ़ न आए।

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

बाधित प्रतीक्षाएँ संभालना

यदि कोई सिग्नल इसे बाधित करता है, तो epoll_wait() errno == EINTR के साथ -1 लौटा सकता है। यह वास्तविक त्रुटि नहीं है; बस दोबारा प्रयास करें।

मज़बूत लूप EINTR मिलने पर जारी रहते हैं और केवल अन्य त्रुटि कोड को गंभीर मानते हैं। इसे भूलने पर सर्वर को पहली बार सिग्नल मिलने पर क्रैश हो सकता है।

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

एक लूप, अनेक क्लाइंट

सभी हिस्सों को जोड़ने पर एक अकेला थ्रेड हमेशा तैयार वर्णनकर्ताओं के बीच चक्र लगाता रहता है: स्वीकार करना, पढ़ना, लिखना, बंद करना और दोहराना।

निष्क्रिय होने पर थ्रेड epoll_wait() में सोता है और व्यस्त होने पर केवल तैयार काम करता है, इसलिए यह डिज़ाइन एक साथ चल रहे हज़ारों कनेक्शन को आसानी से संभाल लेता है।

त्वरित जाँच

इवेंट लूप की अपनी समझ जाँचें।

पुनरावलोकन

इवेंट लूप epoll_wait() को कॉल करता है, तैयार इवेंट पर क्रम से जाता है और कार्य सौंपता है: सुनने वाले सॉकेट पर स्वीकार करना, EPOLLIN पर पढ़ना, EPOLLOUT पर बफ़र खाली करना और हैंग-अप पर सफ़ाई करना।

स्वीकृति और पढ़ने की प्रक्रियाओं को लूप में चलाएँ, EINTR पर दोबारा प्रयास करें और EPOLLET में डेटा पूरी तरह खाली करें। अब हम एक पूरा echo सर्वर बनाएँगे।

शुरुआत निःशुल्क

एआई शिक्षक के साथ C सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
39
पाठ
144

अक्सर पूछे जाने वाले प्रश्न

क्या “Event Loop” पाठ निःशुल्क है?

हाँ—“Event Loop” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और C Academy पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। C Academy पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“Event Loop” में मैं क्या सीखूँगा?

पढ़े जा सकने वाले Sockets पर प्रतिक्रिया दें। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ C Academy का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या C Academy शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर C Academy शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 3वाँ पाठ है।

“Event Loop” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस C Academy पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर C Academy पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. Blocking बनाम Non-Blocking I/O
  2. epoll सेट अप करना
  3. Event Loop
  4. सरल Echo Server
← C Academy पर वापस जाएँ