0Pricing
Lua Academy · درس

إنشاء خادم

اقبل الاتصالات الواردة

إنشاء خادم درس مجاني في Lua Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Lua Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Lua Academy 4 دروس في المجموع.

دورة حياة الخادم

يربط خادم TCP عنوانًا، ويستمع إلى الاتصالات، ثم يكرر قبول العملاء وخدمتهم.

في LuaSocket، تنشئ كائنًا رئيسيًا باستخدام socket.tcp()، وتحوله إلى خادم مستمع باستخدام bind/listen، وتسحب العملاء من قائمة الانتظار باستخدام accept.

local socket = require("socket")
local server = assert(socket.tcp())

الربط بمنفذ

يحجز server:bind(host, port) عنوانًا محليًا. استخدم "*" أو "0.0.0.0" لقبول الاتصالات على كل الواجهات، أو "127.0.0.1" للاتصالات المحلية فقط.

يفشل الربط مع "address already in use" إذا كانت عملية أخرى تستخدم المنفذ.

server:setoption("reuseaddr", true)
local ok, err = server:bind("*", 8080)
if not ok then error("bind failed: " .. err) end

الاستماع للعملاء

يضع server:listen(backlog) المقبس في الوضع السلبي ويبدأ في وضع المصافحات الواردة في قائمة انتظار. ويمثل backlog الحد الأقصى لعدد الاتصالات المعلقة.

ينفذ الاختصار socket.bind(host, port, backlog) عمليتي الربط والاستماع في استدعاء واحد، ويعيد كائن خادم جاهزًا.

local socket = require("socket")
local server = assert(socket.bind("*", 8080, 32))
print("listening on", server:getsockname())

قبول اتصال

ينتظر server:accept() حتى يتصل عميل، ثم يعيد كائن عميل TCP جديدًا تمامًا لذلك الطرف. ويواصل مقبس الخادم نفسه الاستماع.

في مقبس خادم ذي مهلة، يعيد accept القيمة nil, "timeout"، ما يتيح لك تنفيذ أعمال أخرى بالتناوب.

local client, err = server:accept()
if client then
  print("client from", client:getpeername())
end

خدمة عميل واحد

بعد القبول، تعامل مع الكائن المعاد تمامًا كما تتعامل مع مقبس عميل: استقبل الطلبات باستخدام receive وأرسل الاستجابات باستخدام send.

امنح مقبس كل عميل مهلة خاصة به حتى لا يؤدي عميل بطيء واحد إلى تعطيل الخادم بأكمله.

client:settimeout(10)
local line = client:receive("*l")
if line then client:send(line .. "\n") end
client:close()

حلقة القبول

يعمل الخادم التكراري التقليدي في حلقة لا نهائية: يقبل عميلًا، ويخدمه، ويغلقه، ثم يكرر العملية. ويتعامل هذا الأسلوب مع عميل واحد في كل مرة.

إنه بسيط وصحيح، لكنه لا يستطيع خدمة عملاء متزامنين، لأن طلبًا بطيئًا يحجب جميع الطلبات التي تليه.

while true do
  local c = server:accept()
  if c then
    local msg = c:receive("*l")
    if msg then c:send(msg .. "\r\n") end
    c:close()
  end
end

خادم صدى بسيط

عند جمع الأجزاء، يربط خادم الصدى ويستمع، ثم يكرر إعادة السطر الأول لكل عميل.

هذا هو أصغر خادم LuaSocket مكتمل، كما أنه هدف مفيد للعميل الذي أنشأته سابقًا.

local socket = require("socket")
local s = assert(socket.bind("*", 8080))
while true do
  local c = s:accept()
  c:send((c:receive("*l") or "") .. "\r\n")
  c:close()
end

التزامن باستخدام select

لخدمة العديد من العملاء في الوقت نفسه من دون خيوط، استخدم socket.select. ويعيد المقابس الجاهزة للقراءة، بما فيها خادم الاستماع عندما ينتظر عميل جديد.

تدير جدولًا بالعملاء النشطين وتعالج فقط العملاء الذين لديهم بيانات، مما يحافظ على استجابة حلقة الأحداث أحادية الخيط.

local readable = socket.select(watch, nil, 1)
for _, sock in ipairs(readable) do
  if sock == server then
    table.insert(watch, server:accept())
  end
end

قبول غير حاجب

اضبط server:settimeout(0) حتى لا يحجب القبول التنفيذ أبدًا. واجمعه مع select بحيث لا تستدعي accept إلا عندما يكون المستمع قابلًا للقراءة فعلًا.

يشكّل هذا أساس خادم قابل للتوسع ضمن عملية واحدة، ويُعدّد مئات الاتصالات.

server:settimeout(0)
local ready = socket.select({server}, nil, 5)
if #ready > 0 then
  local c = server:accept()
end

معالجة أخطاء العملاء

قد يقطع العملاء الاتصال فجأة. عندما يعيد receive القيمة nil, "closed" أو مخزنًا مؤقتًا جزئيًا، أزل ذلك العميل من جدول المراقبة وأغلق مقبسه.

لا تسمح أبدًا لاتصال واحد معطوب بإيقاف حلقة القبول؛ اعزل إخفاقات كل عميل.

local data, err = client:receive("*l")
if err == "closed" then
  client:close()
  remove_from_watch(client)
end

إيقاف تشغيل نظيف

عند إيقاف التشغيل، أوقف قبول الاتصالات، وأغلق كل مقبس عميل نشط، ثم أغلق خادم الاستماع لتحرير المنفذ.

يتيح ضبط reuseaddr وقت الربط إعادة التشغيل فورًا من دون انتظار انتهاء فترة TCP TIME_WAIT.

for _, c in ipairs(clients) do c:close() end
server:close()
print("server stopped")

تحقق سريع

اختر تسلسل الاستدعاءات الذي يحوّل مقبسًا رئيسيًا جديدًا إلى مستمع عامل.

مراجعة

أنشأت خادم TCP: ربطته باستخدام reuseaddr، وجعلته يستمع باستخدام backlog، وكررت استدعاء accept لخدمة العملاء.

رأيت الحلقة التكرارية البسيطة، ثم وسّعتها باستخدام socket.select لتحقيق التزامن غير الحاجب، إلى جانب عزل الأخطاء وإيقاف التشغيل النظيف. بعد ذلك ستنتقل إلى مستوى HTTP.

الأسئلة الشائعة

هل درس «إنشاء خادم» مجاني؟

نعم — نص درس «إنشاء خادم» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Lua Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Lua Academy 4 دروس في المجموع.

ماذا ستتعلم في «إنشاء خادم»؟

اقبل الاتصالات الواردة تتمرن على Lua Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Lua Academy؟

لا تُشترط خبرة سابقة. Lua Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «إنشاء خادم»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Lua Academy هذا؟

نعم. كل درس في Lua Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. أساسيات TCP
  2. إنشاء عميل
  3. إنشاء خادم
  4. طلبات HTTP
← العودة إلى Lua Academy