Rust में नेटवर्क प्रोग्रामिंग: तेज़ और सुरक्षित TCP सर्वर लिखना

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

Rust नेटवर्क प्रोग्रामिंग का नया राजा क्यों है?

\n\n

क्या आपने कभी C या C++ में नेटवर्क सर्वर लिखा है और भूल गए म्यूटेक्स के कारण segmentation fault पकड़ा है? या Go में डेटा रेस से जूझते हुए यह समझने की कोशिश की है कि गोरूटीन क्यों "अटक" गई? Rust इन समस्याओं को हमेशा के लिए हल करता है। इसकी स्वामित्व प्रणाली (ownership) और "निडर समवर्ती" (fearless concurrency) मॉडल Rust में नेटवर्क प्रोग्रामिंग को न केवल सुरक्षित बनाता है, बल्कि अविश्वसनीय रूप से प्रदर्शनकारी भी बनाता है।

\n\n

इस लेख में, हम देखेंगे कि मानक लाइब्रेरी (std::net) और Tokio पर आधारित आधुनिक async-स्टैक दोनों का उपयोग करके Rust में TCP और UDP सर्वर कैसे बनाएं। आप देखेंगे कि Rust केवल सिस्टम प्रोग्रामिंग की भाषा नहीं है, बल्कि उच्च-लोड नेटवर्क सेवाएं लिखने के लिए भी एक उत्कृष्ट उपकरण है।

\n\n

मूल बातें: std::net — 5 मिनट में TCP इको सर्वर

\n\n

चलिए क्लासिक से शुरू करते हैं — इको सर्वर। यह TCP कनेक्शन स्वीकार करता है, डेटा पढ़ता है और इसे वापस क्लाइंट को भेजता है। Rust में यह आश्चर्यजनक रूप से संक्षिप्त है।

\n\n
use std::io::{Read, Write};\nuse std::net::{TcpListener, TcpStream};\nuse std::thread;\n\nfn handle_client(mut stream: TcpStream) {\n    let mut buffer = [0; 1024];\n    loop {\n        match stream.read(&mut buffer) {\n            Ok(0) => {\n                println!("क्लाइंट डिस्कनेक्ट हो गया");\n                break;\n            }\n            Ok(n) => {\n                if let Err(e) = stream.write_all(&buffer[..n]) {\n                    eprintln!("लिखने में त्रुटि: {}", e);\n                    break;\n                }\n            }\n            Err(e) => {\n                eprintln!("पढ़ने में त्रुटि: {}", e);\n                break;\n            }\n        }\n    }\n}\n\nfn main() -> std::io::Result<()> {\n    let listener = TcpListener::bind("127.0.0.1:7878")?;\n    println!("सर्वर पोर्ट 7878 पर शुरू हुआ");\n\n    for stream in listener.incoming() {\n        match stream {\n            Ok(stream) => {\n                thread::spawn(|| handle_client(stream));\n            }\n            Err(e) => {\n                eprintln!("कनेक्शन त्रुटि: {}", e);\n            }\n        }\n    }\n    Ok(())\n}\n
\n\n

यहाँ क्या हो रहा है? TcpListener::bind एक सुनने वाला सॉकेट बनाता है। incoming() विधि आने वाले कनेक्शनों पर एक इटरेटर लौटाती है। प्रत्येक नए क्लाइंट के लिए, हम एक अलग थ्रेड शुरू करते हैं — thread::spawn। handle_client के अंदर, हम डेटा को बफर में पढ़ते हैं और write_all के माध्यम से वापस भेजते हैं।

\n\n

महत्वपूर्ण: Rust गारंटी देता है कि TcpStream का उपयोग दो थ्रेड्स से एक साथ नहीं किया जाएगा — कंपाइलर ऐसा करने ही नहीं देगा। इसे ही fearless concurrency कहते हैं।

\n\n

इस दृष्टिकोण की समस्याएं

\n
    \n
  • स्केलिंग: प्रत्येक क्लाइंट एक अलग थ्रेड है। 10,000 क्लाइंट पर OS बस थक जाएगा।
  • \n
  • संसाधन: डिफ़ॉल्ट थ्रेड स्टैक 2 MB है। 10,000 क्लाइंट = 20 GB मेमोरी।
  • \n
\n\n

यहाँ पर एसिंक्रोनस प्रोग्रामिंग मदद करती है।

\n\n

Async क्रांति: Tokio और async/await

\n\n

Rust में अंतर्निहित एसिंक्रोनस रनटाइम नहीं है (जैसे Go या Node.js में)। इसके बजाय, यह Future ट्रेट्स और async/await कीवर्ड प्रदान करता है, और रनटाइम का चुनाव आप पर है। सबसे लोकप्रिय Tokio है। यह सिर्फ एक लाइब्रेरी नहीं है, बल्कि एक संपूर्ण इकोसिस्टम है: TCP/UDP, फ़ाइल I/O, टाइमर, चैनल और यहां तक कि अपना स्वयं का शेड्यूलर।

\n\n

आइए अपने इको सर्वर को Tokio पर फिर से लिखें।

\n\n

Tokio इको सर्वर

\n

Cargo.toml में जोड़ें:

\n
[dependencies]\ntokio = { version = "1", features = ["full"] }
\n\n

अब कोड:

\n\n
use tokio::io::{AsyncReadExt, AsyncWriteExt};\nuse tokio::net::TcpListener;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {

ब्लॉग

पुस्तक अनुशंसाएँ