مقابسُ TCP وUDP مباشرةً
وصفةٌ لمهمّةٍ بعينِها: بروتوكولٌ من عندِك على TCP أو UDP، بلا HTTP. الدوالُّ مُعلَنةٌ في language-truth/builtins/sockets.yaml — ١٩ مدخلًا كلُّها مستقرّة، وتلزمُها استورد مقابس (لا شبكة).
صدى TCP — عمليّتان
الوصفةُ ههنا برنامجانِ مستقلّان لا برنامجٌ بخيطَين، وذلك مقصودٌ ومقيس: راجعِ الحدَّ المقيسَ في آخرِ الصفحة.
الخادم — خادم_مقبس.ص:
استورد مقابس
متغير الخادم = أنشئ_وصلة()
خصص_منفذ(الخادم، 8734)
انتظر_اتصالات(الخادم)
اطبع_سطر("أنتظرُ على المنفذ 8734")
حدد_انتظار_الاستقبال(الخادم، 15000)
متغير المتصل = اقبل_متصل(الخادم)
إذا (المتصل > 0)
حدد_انتظار_الاستقبال(المتصل، 5000)
متغير الرسالة = استقبل_عبر_وصلة(المتصل، 256)
اطبع_سطر("وصلني: " + الرسالة)
أرسل_عبر_وصلة(المتصل، "صدى: " + الرسالة)
أغلق_وصلة(المتصل)
نهاية
أغلق_وصلة(الخادم)العميل — عميل_مقبس.ص:
استورد مقابس
متغير الوصلة = أنشئ_وصلة()
اطبع_سطر(اتصل_بـ(الوصلة، "127.0.0.1"، 8734))
أرسل_عبر_وصلة(الوصلة، "مرحبا")
حدد_انتظار_الاستقبال(الوصلة، 5000)
اطبع_سطر(استقبل_عبر_وصلة(الوصلة، 256))
أغلق_وصلة(الوصلة)sad-build خادم_مقبس.ص -o خادم_مقبس.exe
sad-build عميل_مقبس.ص -o عميل_مقبس.exeشغِّلِ الخادمَ في طرفيّةٍ ثمّ العميلَ في أخرى. مخرَجٌ مقيس:
# الخادم
أنتظرُ على المنفذ 8734
وصلني: مرحبا
# العميل
صحيح
صدى: مرحبادوالُّ TCP
| الدالّة | الوسائطُ المُعلَنة | تفعل |
|---|---|---|
أنشئ_وصلة() | — | مِقبضُ مقبسٍ جديد |
خصص_منفذ(الوصلة، المنفذ) | ٢ | يحجزُ منفذًا (و0 يعني منفذًا مؤقّتًا) |
انتظر_اتصالات(الوصلة) | ١–٢ | يفتحُ طابورَ الاستماع |
اقبل_متصل(الوصلة) | ١ | يقبلُ اتّصالًا ويُرجِعُ مِقبضَه |
اتصل_بـ(الوصلة، العنوان، المنفذ) | ٣ | يتّصلُ بخادم |
أرسل_عبر_وصلة(الوصلة، النص) | ٢ | يُرسِل |
استقبل_عبر_وصلة(الوصلة، الحجم) | ١–٢ | يستقبلُ حتّى الحجم بايتًا |
أغلق_وصلة(الوصلة) | ١ | يُغلِق |
هل_متصلة(الوصلة) | ١ | حالةُ الاتّصال |
منفذ_محلي(الوصلة) | ١ | المنفذَ الذي حُجِزَ فعلًا |
عنوان_الطرف_الآخر(الوصلة) | ١ | عنوانَ النظير |
رسالةُ UDP — عمليّتان
المستقبِل:
استورد مقابس
متغير المستقبل = أنشئ_مرسال()
خصص_منفذ_رسائل(المستقبل، 8735)
حدد_انتظار_الاستقبال(المستقبل، 15000)
اطبع_سطر("أنتظرُ رسالةً على 8735")
متغير الرسالة = استقبل_رسالة(المستقبل، 256)
اطبع_سطر("وصلني: " + الرسالة)
أغلق_مرسال(المستقبل)المرسِل:
استورد مقابس
متغير المرسال = أنشئ_مرسال()
خصص_منفذ_رسائل(المرسال، 0)
اطبع_سطر("منفذي المحلي > 0: " + نص(منفذ_محلي(المرسال) > 0))
اطبع_سطر(أرسل_رسالة(المرسال، "مرحبا عبر UDP"، "127.0.0.1"، 8735) > 0)
أغلق_مرسال(المرسال)مخرَجٌ مقيس:
# المستقبِل
أنتظرُ رسالةً على 8735
وصلني: مرحبا عبر UDP
# المرسِل
منفذي المحلي > 0: صحيح
صحيح| الدالّة | الوسائطُ المُعلَنة | تفعل |
|---|---|---|
أنشئ_مرسال() | — | مِقبضُ مقبسِ رسائل |
خصص_منفذ_رسائل(المرسال، المنفذ) | ٢ | يحجزُ منفذًا |
أرسل_رسالة(المرسال، النص، العنوان، المنفذ) | ٤ | يُرسِلُ مخطّطَ بيانات |
استقبل_رسالة(المرسال، الحجم) | ١–٢ | يستقبِل |
أغلق_مرسال(المرسال) | ١ | يُغلِق |
إعداداتٌ مشتركة
| الدالّة | تفعل |
|---|---|
حدد_انتظار_الاستقبال(المقبس، مِلّي) | مهلةَ الاستقبال |
حدد_انتظار_الإرسال(المقبس، مِلّي) | مهلةَ الإرسال |
أرسل_فورا(المقبس، صحيح) | يُعطّلُ تجميعَ Nagle |
اضبطِ المهلةَ قبلَ كلِّ انتظار
مقبسٌ بلا مهلةٍ يتعلّقُ إلى الأبد. والوصفتانِ أعلاه تضبطانِ المهلةَ قبلَ كلِّ اقبل_متصل واستقبل_*.
حدٌّ مقيس: الصدى داخلَ عمليّةٍ واحدة
النمطُ الشائعُ — خادمٌ في أطلق وعميلٌ في الخيطِ الرئيس داخلَ برنامجٍ واحد — لم ينجح تحتَ المترجِّم: كُتِبَ فتُرجِمَ بلا خطأٍ ثمّ عُلِّقَ حتّى انتهاءِ المهلة. وأُعيدَ القياسُ على بذرةِ المستودعِ نفسِها (tests/behavior/…/05_شبكة/061_tcp_echo_real.ص) فعُلِّقَت مثلَه — وهي موسومةٌ @skip_compiler في الشجرة، أي أنّ الفجوةَ مُعلَنةٌ ومعدودة لا مفاجأة.
فالوصفتانِ أعلاه بعمليّتَينِ لأنّ ذلك ما قِيسَ عاملًا.