مكتبات WebSocket في Rust: Tokio-tungstenite و async-tungstenite
في تطوير الويب الحديث، أصبح بروتوكول WebSocket معيارًا لإنشاء تطبيقات الوقت الفعلي: الدردشات، الألعاب عبر الإنترنت، مؤشرات الأسعار المالية، وأنظمة الإشعارات. يقدم نظام Rust البيئي أدوات قوية وآمنة للعمل مع WebSocket، ومن أبرزها tokio-tungstenite و async-tungstenite. تم بناء هذه المكتبات على أساس بيئة التشغيل غير المتزامنة الشهيرة Tokio ومكدس WebSocket عالي الأداء tungstenite.
ما هما Tokio-tungstenite و async-tungstenite؟
Tokio-tungstenite هي مكتبة WebSocket غير متزامنة لـ Rust، متكاملة مع بيئة التشغيل Tokio. توفر تجريدات ملائمة لإنشاء خوادم وعملاء WebSocket باستخدام الأنواع القياسية لـ Tokio (TcpListener، TcpStream).
Async-tungstenite هي نسخة أكثر عمومية تعمل مع أي بيئة تشغيل غير متزامنة (Tokio، async-std، smol) عبر traits AsyncRead و AsyncWrite. توفر كلتا المكتبتين دعمًا كاملاً لـ RFC 6455، بما في ذلك تجزئة الرسائل، ping/pong، والإخفاء.
الميزات الرئيسية
- غير متزامنة — عمليات غير محظورة باستخدام
async/await - أداء عالٍ — تكاليف إضافية ضئيلة بفضل تحليل zero-copy
- أمان الأنواع — الرسائل ممثلة كهياكل محددة الأنواع بدقة
- مرونة — دعم كل من جانب الخادم والعميل
- SSL/TLS — دعم مدمج للاتصالات الآمنة عبر
rustlsأوnative-tls - إدارة تلقائية للاتصالات — معالجة الانقطاعات وإعادة الاتصال
التثبيت
أضف إلى Cargo.toml:
[dependencies]tokio = { version = "1", features = ["full"] }tokio-tungstenite = "0.21"futures-util = "0.3"مثال: خادم WebSocket
لننشئ خادم echo بسيط يعيد إرسال الرسالة المستلمة:
use tokio::net::TcpListener;use tokio_tungstenite::accept_async;use futures_util::{SinkExt, StreamExt};use std::error::Error;
#[tokio::main]async fn main() -> Result<(), Box> { let listener = TcpListener::bind("127.0.0.1:8080").await?; println!("خادم WebSocket قيد التشغيل على ws://127.0.0.1:8080");
while let Ok((stream, addr)) = listener.accept().await { println!("اتصال جديد: {}", addr); tokio::spawn(handle_connection(stream)); } Ok(())}
async fn handle_connection(stream: tokio::net::TcpStream) { let ws_stream = accept_async(stream).await.expect("خطأ في المصافحة"); let (mut write, mut read) = ws_stream.split();
while let Some(Ok(msg)) = read.next().await { if msg.is_text() || msg.is_binary() { // إرسال الرسالة مرة أخرى if let Err(e) = write.send(msg).await { eprintln!("خطأ في الإرسال: {}", e); break; } } } println!("تم إغلاق الاتصال");} مثال: عميل WebSocket
نتصل بالخادم ونرسل تحية:
use tokio_tungstenite::connect_async;use futures_util::{SinkExt, StreamExt};use url::Url;
#[tokio::main]async fn main() -> Result<(), Box> { let url = Url::parse("ws://127.0.0.1:8080")?; let (ws_stream, _) = connect_async(url).await?; println!("تم الاتصال بالخادم");
let (mut write, mut read) = ws_stream.split();
// إرسال رسالة write.send("مرحبًا بالعالم!".into()).await?; println!("تم الإرسال: مرحبًا بالعالم!");
// قراءة الرد if let S أيضاً في المكتبة
إرسال الرسائل القصيرة (SMS) باستخدام C# (.NET): التكامل مع واجهات برمجة تطبيقات (API) خدمات SMS
ORM لجافا سكريبت (Node.js): مقارنة بين Sequelize و TypeORM و Prisma
التخزين المؤقت في C# (.NET): Redis وMemoryCache وحلول أخرى
Event Bus ونمط Observer في JavaScript (Node.js) — بناء أنظمة أحداث مرنة
العمل مع أرشيفات ZIP في Go (Golang) — دليل كامل