0Pricing
Lua Academy · درس

أساسيات TCP

اتصل وأرسل البيانات

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

ما هي LuaSocket؟

LuaSocket هي مكتبة الشبكات المتعارف عليها بحكم الواقع للغة Lua. وهي توفر مقابس TCP وUDP منخفضة المستوى، بالإضافة إلى أدوات مساعدة عالية المستوى لـ HTTP وSMTP وFTP.

وهي وحدة خارجية مكتوبة بلغة C، ولذلك لا تُعد جزءًا من Lua القياسية. ثبّتها عبر LuaRocks وحمّلها باستخدام require.

لا تعمل أي من المقاطع البرمجية في هذه الدورة على بيئة تجريبية عادية، لأنها تتصل بالشبكة.

local socket = require("socket")
print(socket._VERSION)

إنشاء مقبس TCP

الكائن الأساسي هو مقبس TCP الرئيسي، ويُنشأ باستخدام socket.tcp(). يكون المقبس الرئيسي حديث الإنشاء غير متصل وغير مرتبط.

ومن المقبس الرئيسي، يمكنك إما استخدام connect، لتحويله إلى كائن عميل، أو استخدام bind+listen، لتحويله إلى كائن خادم.

تعيد معظم الاستدعاءات إما قيمة، أو nil بالإضافة إلى سلسلة خطأ، لذا احرص دائمًا على التقاط القيمتين.

local socket = require("socket")
local tcp, err = socket.tcp()
if not tcp then error(err) end

عائلة العناوين

يعمل TCP عبر IPv4 أو IPv6. يختار socket.tcp() عائلة العناوين عند الحاجة، بينما يفرض socket.tcp4() وsocket.tcp6() استخدام إحداهما.

استخدم socket.dns.toip(host) لتحويل اسم المضيف إلى عنوان رقمي قبل الاتصال إذا كنت تحتاج إلى تحكم صريح.

local socket = require("socket")
local ip, info = socket.dns.toip("example.com")
print(ip)

الاتصال بمضيف

ينفّذ conn:connect(host, port) المصافحة الثلاثية لـ TCP. ويعيد 1 عند النجاح، ويعيد nil ورسالة خطأ عند الفشل، مثل "connection refused" أو "timeout".

تنشئ الدالة المساعدة socket.connect(host, port) مقبسًا وتتصل به في استدعاء واحد.

local socket = require("socket")
local conn, err = socket.connect("example.com", 80)
if not conn then print("failed:", err) end

إرسال البيانات

يكتب conn:send(data) البايتات إلى المقبس. ويعيد فهرس آخر بايت أُرسل. ومع المقبس المحظور، يكون هذا عادةً طول data بالكامل.

TCP عبارة عن تدفق من البايتات، وليس بروتوكول رسائل، لذلك قد يؤدي send واحد إلى تقسيم البيانات أو دمجها أثناء النقل. وعليك تحديد إطارات رسائلك بنفسك.

local request = "GET / HTTP/1.0\r\n\r\n"
local sent, err = conn:send(request)
print("bytes sent:", sent)

استقبال البيانات

يقرأ conn:receive(pattern) من التدفق. ويقرأ النمط الافتراضي "*l" سطرًا واحدًا من دون محرف السطر الجديد. أما "*a" فيقرأ حتى يُغلق الاتصال.

يمكنك أيضًا تمرير رقم لقراءة هذا العدد من البايتات بالضبط. وعند حدوث خطأ، يعيد nil وسلسلة خطأ وأي بيانات جزئية تم استقبالها.

local line, err = conn:receive("*l")
local chunk = conn:receive(512)
local all = conn:receive("*a")

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

استدعِ دائمًا conn:close() عند الانتهاء لتحرير واصف الملف وإرسال TCP FIN.

يمكنك إجراء إغلاق نصفي باستخدام conn:shutdown("send") للإشارة إلى نهاية التدفق مع الاستمرار في قراءة استجابة الطرف الآخر. ويفيد ذلك في بروتوكولات الطلب والاستجابة التي تستخدم "*a".

conn:shutdown("send")
local reply = conn:receive("*a")
conn:close()

أهمية المهلات الزمنية

تحظر المقابس افتراضيًا إلى أجل غير مسمى. ويحدد conn:settimeout(seconds) المدة القصوى التي ينتظرها الاستدعاء. وتجعل القيمة 0 المقبس غير حاجب.

عند انتهاء المهلة، يعيد الاستدعاء nil والسلسلة "timeout". احرص دائمًا على ضبط مهلة زمنية في بيئة الإنتاج لتجنب الاتصالات المعلقة.

conn:settimeout(5)
local data, err = conn:receive("*l")
if err == "timeout" then print("too slow") end

TCP مقابل UDP

يتميّز TCP بأنه قائم على الاتصال، ومرتّب، وموثوق؛ إذ تصل البايتات مرة واحدة وبالترتيب، مقابل تكلفة عمليات المصافحة وإعادة الإرسال.

أما UDP (socket.udp()) فهو عديم الاتصال وغير موثوق، لكنه خفيف، ما يجعله مناسبًا للقياس عن بُعد أو الألعاب. يركّز هذا المقرر على TCP لأنه يشكّل أساس HTTP.

الإرسال الجزئي والحلقات

في المقابس غير الحاجبة، قد يرسل send جزءًا فقط من المخزن المؤقت. ويعيد nil و"timeout" وفهرس آخر بايت كُتب حتى تلك اللحظة.

يستخدم المُرسِل المتين حلقةً لمتابعة الإرسال بدءًا من البايت الذي يلي آخر بايت أُرسل، حتى يُفرَّغ المخزن المؤقت بالكامل.

local i = 1
while i <= #data do
  local sent, err, last = conn:send(data, i)
  i = (sent or last) + 1
  if err and err ~= "timeout" then break end
end

فحص الاتصال

يعيد conn:getpeername() عنوان IP والمنفذ البعيدين، بينما يعيد conn:getsockname() الطرف المحلي. وتفيد هذه المعلومات في التسجيل وتصحيح الأخطاء.

تضبط conn:setoption("keepalive", true) وconn:setoption("tcp-nodelay", true) سلوك المقبس الأساسي.

local ip, port = conn:getpeername()
print("connected to", ip, port)
conn:setoption("tcp-nodelay", true)

تحقق سريع

اختبر مدى فهمك لدلالات الاستقبال في TCP.

مراجعة

تعرّفت إلى الكائن الرئيسي في TCP ضمن LuaSocket، وتعلّمت إنشاء المقابس وتوصيلها وإرسال البيانات واستقبالها وإغلاقها، كما رأيت كيف تؤثر المهلات والإغلاق النصفي في السلوك.

تذكّر أن TCP عبارة عن تدفق من البايتات، وأن كل استدعاء قد يعيد nil, err، وأن مقبس الإنتاج يضبط مهلةً دائمًا. بعد ذلك ستجمع هذه الأجزاء في عميل عامل.

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

هل درس «أساسيات TCP» مجاني؟

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

ماذا ستتعلم في «أساسيات TCP»؟

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

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

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

كم من الوقت يستغرق درس «أساسيات TCP»؟

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

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

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

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

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