WebSocket على Rust: تطبيقات الوقت الفعلي من الألف إلى الياء

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة حول WebSocket على Rust: لماذا هو اختيار المحترفين



تتطلب تطبيقات الويب الحديثة نقلًا فوريًا للبيانات. سواء كانت دردشة عبر الإنترنت، أو محطة تداول، أو لعبة متعددة اللاعبين، أو نظام مراقبة - أصبح بروتوكول WebSocket المعيار للاتصالات في الوقت الفعلي. Rust، مع تركيزها على الأداء وأمان الذاكرة، هي منصة مثالية لبناء مثل هذه الأنظمة.



في هذه المقالة، سنقوم بشرح إنشاء تطبيقات WebSocket على Rust من الصفر. ستتعلم كيفية عمل المكتبات الأساسية، وكيفية التعامل مع اتصالات متعددة، وكيفية بناء أنظمة وقت فعلي قابلة للتوسع. المادة موجهة للمطورين الملمين بأساسيات Rust والبرمجة غير المتزامنة.



1. أساسيات WebSocket في Rust: اختيار المكتبة



تقدم بيئة Rust العديد من الحلول الناضجة للعمل مع WebSocket. الأكثر شيوعًا:



  • tokio-tungstenite - WebSocket غير متزامن يعتمد على tokio، منخفض المستوى ومرن
  • warp - إطار عمل ويب مع دعم مدمج لـ WebSocket
  • actix-web - إطار عمل قوي مع دعم WebSocket


لأغراض هذا الدليل، سنختار tokio-tungstenite كأكثر حل شامل.



تثبيت التبعيات



أنشئ مشروعًا جديدًا وأضف إلى Cargo.toml:



[dependencies]tokio = { version = "1", features = ["full"] }tokio-tungstenite = "0.21"futures-util = "0.3"serde = { version = "1", features = ["derive"] }serde_json = "1"


خادم WebSocket أساسي



لنكتب خادم صدى بسيطًا يعيد إرسال الرسالة المستلمة:



use futures_util::{SinkExt, StreamExt};use tokio::net::TcpListener;use tokio_tungstenite::accept_async;use tokio_tungstenite::tungstenite::Message;

#[tokio::main]async fn main() { let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap(); println!("تم تشغيل الخادم على ws://127.0.0.1:8080");

while let Ok((stream, addr)) = listener.accept().await { println!("اتصال جديد: {}", addr); tokio::spawn(handle_connection(stream)); }}

async fn handle_connection(stream: tokio::net::TcpStream) { let ws_stream = accept_async(stream).await.unwrap(); let (mut write, mut read) = ws_stream.split();

while let Some(Ok(msg)) = read.next().await { if let Message::Text(text) = msg { println!("تم الاستلام: {}", text); let response = format!("صدى: {}", text); write.send(Message::Text(response.into())).await.unwrap(); } }}


يوضح هذا الكود البنية الأساسية: خادم TCP غير متزامن، استقبال اتصالات WebSocket، ومعالجة الرسائل في مهام منفصلة.



2. بنية دردشة الوقت الفعلي على Rust



الآن سنبني دردشة كاملة، حيث يتم إرسال الرسائل من عميل واحد إلى جميع المستخدمين المتصلين. لهذا نحتاج إلى حالة مشتركة - قائمة بالاتصالات النشطة.



التنفيذ مع حالة مشتركة



use std::collections::HashMap;use std::sync::Arc;use tokio::sync::{Mutex, broadcast};

type Tx = broadcast::Sender<String>;type Clients = Arc<Mutex<HashMap<String, Tx>>>;

#[tokio::main]async fn main() { let clients: Clients = Arc::new(Mutex::new(HashMap::new())); let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap();

while let Ok((stream, addr)) = listener.accept().await { let clients = clients.clone(); tokio::spawn(handle_client(stream, addr, clients)); }}

async fn handle_client( stream: tokio::net::TcpStream, addr: std::net::SocketAddr, clients: Clients) { let ws_stream = accept_async(stream).await.unwrap(); let (mut write, mut read) = ws_stream.split();

// إنشاء قناة للإرسال الجماعي

المدونات

توصيات الكتب