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

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

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

ابدأ الدورة

مقدمة في WebSocket على Go: لماذا الوقت الفعلي؟



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



Go مثالي لـ WebSocket بفضل نموذج التزامن الخفيف (الغوروتينات) والأداء العالي. سننتقل من خادم الصدى البسيط إلى دردشة كاملة ونظام مراقبة.



أساسيات WebSocket وإعداد البيئة



ما هو WebSocket؟

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



التثبيت والمكتبات

لا توجد مكتبة قياسية لـ WebSocket في Go، ولكن هناك مكتبة شائعة gorilla/websocket. سنقوم بتثبيتها:

go get github.com/gorilla/websocket


يمكنك أيضاً استخدام nhooyr.io/websocket (بديل أكثر حداثة)، لكن في هذه المقالة سنركز على gorilla باعتبارها الأكثر انتشاراً.



أول خادم WebSocket على Go

لنكتب خادم صدى بسيطاً يستقبل الرسالة ويرسلها مرة أخرى:

package main

import ( "log" "net/http" "github.com/gorilla/websocket")

var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true // للتطوير },}

func echoHandler(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Print("Upgrade:", err) return } defer conn.Close()

for { mt, message, err := conn.ReadMessage() if err != nil { log.Println("Read:", err) break } log.Printf("Received: %s", message) err = conn.WriteMessage(mt, message) if err != nil { log.Println("Write:", err) break } }}

func main() { http.HandleFunc("/echo", echoHandler) log.Println("Server started on :8080") log.Fatal(http.ListenAndServe(":8080", nil))}


هذا مثال عملي بسيط. لاحظ Upgrader — فهو يتحقق من رؤوس HTTP ويحول الاتصال.



بنية تطبيق الوقت الفعلي: دردشة على Go



إدارة الاتصالات

للدردشة، نحتاج إلى إدارة العديد من العملاء. لننشئ هيكل Hub الذي سيخزن جميع الاتصالات النشطة ويوزع الرسائل:

type Client struct {    hub  *Hub    conn *websocket.Conn    send chan []byte}

type Hub struct { clients map[*Client]bool broadcast chan []byte register chan *Client unregister chan *Client}

func newHub() *Hub { return &Hub{ clients: make(map[*Client]bool), broadcast: make(chan []byte), register: make(chan *Client), unregister: make(chan *Client), }}

func (h *Hub) run() { for { select { case client := <-h.register: h.clients[client] = true case client := <-h.unregister: if _, ok := h.clients[client]; ok { delete(h.clients, client) close(client.send) } case message := <-h.broadcast: for client := range h.clients { select { case client.send <- message: default:

المدونات

توصيات الكتب