استكشاف WebSocket

Home PDF

تمت مساعدة هذه المدونة بواسطة ChatGPT-4o.


مقدمة

مرحبًا بالجميع، أنا Li Zhiwei. بصفتي المؤسس والمدير التقني لمنصة CodeReview، ومهندس سابق في LeanCloud، لدي خبرة واسعة في مجال WebSocket، خاصة أثناء تطوير SDK للرسائل الفورية (IM).

أهمية WebSocket

WebSocket هو بروتوكول يوفر قناة اتصال ثنائية الاتجاه عبر اتصال TCP واحد. يتم استخدامه على نطاق واسع في التطبيقات الحديثة التي تتطلب تفاعلًا في الوقت الفعلي، مثل المراسلة الفورية، التعليقات الفورية، الألعاب متعددة اللاعبين، التحرير التعاوني، وأسعار الأسهم الفورية.

التطبيقات الحديثة لـ WebSocket

يُستخدم WebSocket على نطاق واسع في المجالات التالية:

تطور WebSocket

الاستطلاع (Polling): يقوم العميل بطلب الخادم بشكل متكرر للحصول على التحديثات. الاستطلاع الطويل (Long Polling): يحتفظ الخادم بالطلب مفتوحًا حتى تتوفر معلومات جديدة. اتصال HTTP ثنائي الاتجاه: يتطلب اتصالات متعددة للإرسال والاستقبال، ويحتوي كل طلب على رؤوس HTTP. اتصال TCP واحد (WebSocket): يتغلب على قيود اتصال HTTP ثنائي الاتجاه، ويوفر قدرات في الوقت الفعلي أعلى وزمن انتقال أقل.

تنفيذ WebSocket على iOS

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

الخطوة 1: إضافة مكتبة Starscream

أولاً، نحتاج إلى إضافة مكتبة Starscream إلى مشروعنا. Starscream هي مكتبة شائعة لتنفيذ WebSocket في Swift.

  1. افتح ملف Podfile وأضف السطر التالي:

    pod 'Starscream', '~> 4.0.0'
    
  2. قم بتشغيل الأمر التالي في Terminal لتثبيت المكتبة:

    pod install
    

الخطوة 2: إنشاء اتصال WebSocket

بعد تثبيت المكتبة، يمكننا البدء في إنشاء اتصال WebSocket.

import Starscream

class WebSocketManager: WebSocketDelegate {
    var socket: WebSocket!

    init() {
        var request = URLRequest(url: URL(string: "wss://yourserver.com")!)
        request.timeoutInterval = 5
        socket = WebSocket(request: request)
        socket.delegate = self
        socket.connect()
    }

    func didReceive(event: WebSocketEvent, client: WebSocket) {
        switch event {
        case .connected(let headers):
            print("WebSocket is connected: \(headers)")
        case .disconnected(let reason, let code):
            print("WebSocket is disconnected: \(reason) with code: \(code)")
        case .text(let string):
            print("Received text: \(string)")
        case .binary(let data):
            print("Received data: \(data.count)")
        case .ping(_):
            break
        case .pong(_):
            break
        case .viabilityChanged(_):
            break
        case .reconnectSuggested(_):
            break
        case .cancelled:
            print("WebSocket is cancelled")
        case .error(let error):
            print("WebSocket encountered an error: \(String(describing: error))")
        }
    }

    func sendMessage(_ message: String) {
        socket.write(string: message)
    }

    func disconnect() {
        socket.disconnect()
    }
}

الخطوة 3: استخدام WebSocketManager

الآن بعد أن أنشأنا WebSocketManager، يمكننا استخدامه في أي جزء من التطبيق لإرسال واستقبال الرسائل.

let webSocketManager = WebSocketManager()

// إرسال رسالة
webSocketManager.sendMessage("Hello, Server!")

// قطع الاتصال
webSocketManager.disconnect()

الخلاصة

في هذا المقال، تعلمنا كيفية تنفيذ WebSocket في تطبيق iOS باستخدام مكتبة Starscream. يمكن استخدام WebSocket لإنشاء اتصالات في الوقت الفعلي مع الخادم، مما يسمح بتبادل البيانات بسرعة وكفاءة. يمكن توسيع هذا المثال ليشمل المزيد من الميزات مثل إعادة الاتصال التلقائي وإدارة الأخطاء.

مكتبات WebSocket الشهيرة لنظام iOS:

استخدام SRWebSocket

  1. التهيئة والاتصال:
    SRWebSocket *webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"ws://echo.websocket.org"]]];
    webSocket.delegate = self;
    [webSocket open];
    
  2. إرسال الرسالة:
    [webSocket send:@"Hello, World!"];
    
  3. استقبال الرسائل: قم بتنفيذ طرق SRWebSocketDelegate للتعامل مع الرسائل الواردة والأحداث.

  4. معالجة الأخطاء وإشعارات الأحداث: قم بمعالجة الأخطاء بشكل مناسب وأخبر المستخدمين بأي مشاكل في الاتصال.

شرح مفصل لبروتوكول WebSocket

WebSocket هو بروتوكول اتصالات يوفر قناة اتصال ثنائية الاتجاه (Full-Duplex) عبر اتصال TCP واحد. تم تصميمه ليتم تنفيذه في المتصفحات وخوادم الويب، ولكنه يمكن استخدامه أيضًا في أي تطبيق عميل/خادم. يتميز WebSocket بإمكانية إرسال البيانات بين العميل والخادم في الوقت الفعلي دون الحاجة إلى إجراء طلبات HTTP متكررة.

كيف يعمل WebSocket؟

  1. مصافحة اليد (Handshake):
    • يبدأ الاتصال بمصافحة HTTP تُعرف بـ “Upgrade Request”. يرسل العميل طلب HTTP إلى الخادم مع طلب ترقية الاتصال إلى WebSocket.
    • إذا وافق الخادم على الطلب، فإنه يرد برسالة تأكيد ترقية الاتصال إلى WebSocket.
    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    Sec-WebSocket-Version: 13
    
    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    
  2. نقل البيانات:
    • بعد إتمام المصافحة، يتم إنشاء قناة اتصال ثنائية الاتجاه يمكن من خلالها إرسال البيانات بين العميل والخادم.
    • يتم إرسال البيانات في شكل إطارات (Frames) صغيرة، والتي يمكن أن تحتوي على نصوص أو بيانات ثنائية.
  3. إغلاق الاتصال:
    • يمكن لأي من الطرفين (العميل أو الخادم) إغلاق الاتصال بإرسال إطار إغلاق (Close Frame).

مميزات WebSocket:

استخدامات WebSocket:

مثال بسيط باستخدام JavaScript:

// إنشاء اتصال WebSocket
const socket = new WebSocket('ws://example.com/socket');

// فتح الاتصال
socket.onopen = function(event) {
    console.log('Connection established');
    socket.send('Hello Server!');
};

// استقبال الرسائل من الخادم
socket.onmessage = function(event) {
    console.log('Message from server:', event.data);
};

// إغلاق الاتصال
socket.onclose = function(event) {
    console.log('Connection closed');
};
// على جانب الخادم (Node.js مع مكتبة ws)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws) {
    ws.on('message', function incoming(message) {
        console.log('received: %s', message);
    });

    ws.send('Hello Client!');
});

WebSocket هو أداة قوية لبناء تطبيقات تفاعلية في الوقت الفعلي، ويوفر تحسينات كبيرة في الأداء مقارنة بالطرق التقليدية مثل HTTP Long Polling.

يعمل WebSocket فوق بروتوكول TCP ويقدم عدة تحسينات:

أساسيات بروتوكول WebSocket

WebSocket هو بروتوكول اتصالات يوفر قناة اتصال ثنائية الاتجاه (Full-Duplex) عبر اتصال TCP واحد. تم تصميمه ليتم تنفيذه في المتصفحات وخوادم الويب، ولكنه يمكن استخدامه أيضًا في أي تطبيق عميل/خادم. تم تقديم WebSocket كجزء من HTML5، وهو يعمل على تحسين الاتصال بين العميل والخادم مقارنةً بالتقنيات القديمة مثل HTTP Long Polling.

الميزات الرئيسية لـ WebSocket:

  1. ثنائية الاتجاه (Full-Duplex): يمكن للعميل والخادم إرسال البيانات في نفس الوقت دون الحاجة إلى انتظار الطرف الآخر.
  2. اتصال مستمر: بمجرد إنشاء الاتصال، يبقى مفتوحًا حتى يتم إغلاقه من قبل أحد الطرفين.
  3. نقل البيانات الخفيف: يتم إرسال البيانات بتنسيق خفيف الوزن، مما يقلل من النفقات العامة (overhead) مقارنةً ببروتوكولات أخرى مثل HTTP.
  4. دعم للبيانات النصية والثنائية: يمكن إرسال البيانات النصية والثنائية عبر WebSocket.

كيفية عمل WebSocket:

  1. مصافحة (Handshake): يبدأ الاتصال بمصافحة HTTP تُعرف باسم “Upgrade Request”، حيث يطلب العميل من الخادم ترقية الاتصال إلى بروتوكول WebSocket.

    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    Sec-WebSocket-Version: 13
    

    يقوم الخادم بالرد بالموافقة على الترقية:

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    
  2. نقل البيانات: بعد إنشاء الاتصال، يمكن للعميل والخادم إرسال البيانات بشكل مستقل. يتم تقسيم البيانات إلى إطارات (frames) صغيرة يتم إرسالها عبر الاتصال.

  3. إغلاق الاتصال: يمكن لأي من الطرفين إغلاق الاتصال بإرسال إطار إغلاق (Close Frame).

مثال بسيط باستخدام JavaScript:

// إنشاء اتصال WebSocket
const socket = new WebSocket('ws://example.com/socket');

// عند فتح الاتصال
socket.onopen = function(event) {
    console.log('Connection opened');
    socket.send('Hello Server!');
};

// عند استقبال رسالة من الخادم
socket.onmessage = function(event) {
    console.log('Message from server:', event.data);
};

// عند إغلاق الاتصال
socket.onclose = function(event) {
    console.log('Connection closed');
};

// عند حدوث خطأ
socket.onerror = function(error) {
    console.error('WebSocket error:', error);
};

استخدامات WebSocket:

WebSocket يوفر طريقة فعالة ومرنة للتواصل في الوقت الحقيقي بين العميل والخادم، مما يجعله خيارًا مثاليًا للعديد من التطبيقات الحديثة.

1. المصافحة: تستخدم WebSocket آلية الترقية الخاصة بـ HTTP لإتمام المصافحة:

2. نقل البيانات: يمكن أن تحتوي إطارات WebSocket على نصوص بتنسيق UTF-8، وبيانات ثنائية، وإطارات تحكم مثل الإغلاق، وping، وpong.

3. الأمان: يقوم المتصفح تلقائيًا بإضافة رأس Origin، والذي لا يمكن تزويره من قبل العملاء الآخرين.

عنوان WebSocket

بروتوكول إطارات WebSocket

WebSocket هو بروتوكول اتصال ثنائي الاتجاه يعمل فوق اتصال TCP واحد. يتم تقسيم البيانات المرسلة عبر WebSocket إلى إطارات (frames) صغيرة، حيث يتم إرسال كل إطار بشكل مستقل. يتكون بروتوكول إطارات WebSocket من عدة أجزاء رئيسية:

  1. البت الأول (FIN): يشير إلى ما إذا كانت هذه هي الإطار الأخير في الرسالة.
  2. بتات التحكم (Opcode): تحدد نوع الإطار (مثل نص، بيانات ثنائية، إغلاق، إلخ).
  3. بت الإخفاء (Mask): يشير إلى ما إذا كانت البيانات مخفية.
  4. طول الحمولة (Payload Length): يحدد طول البيانات المرسلة.
  5. مفتاح الإخفاء (Masking Key): يستخدم لإخفاء البيانات إذا كان بت الإخفاء مضبوطًا.
  6. البيانات (Payload Data): البيانات الفعلية المرسلة.

مثال على إطار WebSocket

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+

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

هيكل الإطار:

مفتاح القناع (Masking Key): يُستخدم لمنع هجمات الرجل في المنتصف (Man-in-the-Middle) عن طريق إخفاء إطارات العميل.

إغلاق المصافحة

إطار الإغلاق (Close Frame):

مثال

المثال 1: رسالة نصية غير مقنعة بإطار واحد

0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f

تحتوي على “Hello”

المثال الثاني: رسالة نصية بإطار واحد مع قناع

0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58

تحتوي على “Hello” مع مفتاح القناع.

المثال الثالث: رسالة نصية مجزأة بدون قناع

0x01 0x03 0x48 0x65 0x6c
0x80 0x02 0x6c 0x6f

الرسالة المجزأة تحتوي على إطارين: “Hel” و “lo”.

الموضوعات المتقدمة

التعتيم وإزالة التعتيم:

التجزئة (Fragmentation):

إطارات التحكم:

قابلية التوسع

يمكن وضع البيانات الموسعة قبل بيانات التطبيق في جسم الرسالة:

الإرسال:

إغلاق المصافحة:

إغلاق الاتصال:

المراجع

الشكر والتقدير

شكرًا لكم جميعًا على اهتمامكم. إذا كانت لديكم المزيد من الأسئلة أو النقاشات، فلا تترددوا في التواصل معي على GitHub أو Weibo.


Back 2025.01.18 Donate