الخلاصة

  • عرّفت RFC 1921 ثلاثة مسارات معنونة داخل اتصال Telnet واحد: الشاشة والطابعة وطباعة نسخة الشاشة، وسمحت بطلب معلّق واحد لكل عنوان.
  • كان الطلب الثاني إلى العنوان نفسه يُحذف، ثم ينتظر رد PROTOCOL-VIOLATION إلى أن يخرج جواب الطلب الأول؛ فالترتيب قام مقام رقم المعاملة.
  • تفاوض Terminal-Type وحدّ EOR أنشآ صيغة مشتركة فحسب. أما Mailbox وACK وBUSY وREADY فلم تثبت هوية مستخدم ولا تفويضاً ولا نتيجة في التطبيق أو على الورق.

الخطأ المتأخر كان يحمي معنى الجواب

لنفترض أن الخادم أرسل بيانات إلى الطابعة، ثم أرسل طلباً آخر قبل أن يعرف مصير الأول. لا يحمل TNVIP رقماً عاماً يربط كل جواب بمعاملته. لو رد المستقبل فوراً بأن الطلب الثاني مخالف، لظهر هذا الرد في الموضع الذي ينتظر فيه المرسل جواب الطلب الأول. يصبح الخطأ صادقاً في ذاته لكنه مضلل في نسبته.

لذلك فرضت RFC 1921، الصادرة في مارس/آذار 1996 بوصفها وثيقة Informational، ترتيباً أدق. يُحذف الطلب المتعجل. يُستكمل رد الطلب القائم. بعد ذلك فقط يصل إشعار المخالفة. لم تمنح الوثيقة الطلب المحذوف مكاناً خفياً في طابور، ولم تسمح للخطأ بأن يتجاوز الواقعة التي يشرحها.

تلك ليست قاعدة تجميلية. إنها الشرط الذي يجعل سجل بلا معرّفات معاملات قابلاً لإعادة البناء.

اتصال واحد لا يعني حالة واحدة

صُمم TNVIP لمحاكاة محطات Bull من عائلة Visual Information Projection عبر Telnet. كانت تلك المحطات تعمل بالكتل، ويمكن أن تجمع شاشة وطابعة مرتبطة بها. وغالباً ما كان خادم TNVIP بوابة إلى Terminal Manager في بيئة DSA وإلى تطبيقات المضيف.

قسّمت الوثيقة هذا العالم قبل وصف النتائج. يبدأ كل سجل TNVIP برأس من بايتين. الأول عنوان: 0x60 لمسار الشاشة، و0x68 لمسار الطابعة، و0x69 لمسار طباعة نسخة الشاشة. أما البايت الثاني فيحمل الأمر ونوع الرسالة في أدنى بتّين.

نوع indication لا ينتظر جواباً. ونوع request يفتح التزاماً بالرد على العنوان نفسه. ويغلق response ذلك الالتزام. أما response-and-request فيجيب إيجابياً عن الطلب الحالي ويفتح في اللحظة نفسها طلباً جديداً في الاتجاه المقابل.

وهكذا لم يكن السؤال: هل اتصال TCP مشغول؟ بل: ما الطلب القائم في كل مسار؟ قد تنتظر الشاشة جواباً بينما يحمل مسار الطابعة حالة أخرى. الحظر يخص العنوان نفسه، لا الاتصال كله.

ثلاثة دفاتر بدلاً من أرقام لا تنتهي

سمح التصميم بطلب معلّق واحد في كل عنوان. فإذا جاء طلب آخر قبل الجواب، حُذف. كان على المستقبل أن يرسل PROTOCOL-VIOLATION بعد جواب الأول، لا قبله.

بهذه القاعدة استطاع كل طرف أن يتحقق محلياً من الرسالة التالية بواسطة ثلاث حالات صغيرة. لم يحتج إلى سجل مركزي للمعاملات. وكان الثمن واضحاً: توازٍ أقل داخل المسار، وفقد صريح حين يخالف المرسل حد الإيقاع.

يعرض تاريخ LDAP حلاً مغايراً: رسائل متعددة يمكن أن تتداخل، وتعيدها Message IDs إلى عملياتها. لا يجعل ذلك TNVIP بدائياً ولا LDAP مبذراً؛ إنه اختيار بين رقم يسمح بمزيد من التداخل وقاعدة ترتيب تقلل الحالة المشتركة.

الأهم أن الحذف لم يكن انتظاراً. على المرسل أن يقرر لاحقاً إن كان سيعيد بناء الطلب وإرساله. كلمة BUSY لم تنقل مسؤولية إعادة المحاولة إلى مستقبل لم يعد يحتفظ بالبيانات.

إطار مكتمل قد ينتهي إلى الحذف

لأن أجهزة VIP تتعامل مع كتلة كاملة، أنهى TNVIP كل رسالة بـIAC EOR. جاءت آلية End-of-Record من RFC 885 فوق أساس Telnet في RFC 854.

يثبت EOR أن المستقبل عثر على نهاية السجل. لكنه لا يثبت أن الشاشة عرضت المحتوى أو أن مخزن الطابعة قبله أو أن تطبيق DSA أكمل عملاً. لهذا وُجدت استجابات TNVIP الخاصة. الحد النحوي سابق على قرار المعالجة.

وكشفت الوثيقة موضعاً آخر للغموض. فإذا وُضع أمر Telnet داخل رسالة TNVIP، عدا IAC IAC المقتبس، جاز للتنفيذ أن يعالجه فوراً أو بعد معالجة الرسالة. أوصت RFC بقوة بوضع أوامر Telnet بين السجلات. ترتيب البايتات وحده لم يحدد دائماً ترتيب الأثر بين التحكم والبيانات.

اسم المحطة يختار مدخلاً ولا يثبت صاحبه

قبل بدء TNVIP كان نجاح تفاوض Terminal-Type وEOR إلزامياً. حمل نص نوع المحطة اسم نموذج معروف، واستطاع إضافة @Mailbox-name. اختار Mailbox نقطة وصول محددة لدى الخادم، بينما أتاح غيابه وصولاً عاماً. وفي بوابة DSA كان طوله لا يزيد على اثني عشر محرفاً وتُعامل الأحرف الصغيرة كالكبيرة.

هذه وظيفة توجيه منطقية، لا عملية مصادقة. تصف RFC 1091 كيف يُعرض نوع المحطة، ولا تمنح حائز الاسم حق استخدامه. وقد قالت فقرة الأمن في RFC 1921 إن قضايا الأمن غير معالجة، وتوقعت أن تساعد مصادقة مستقبلية في الإجابة عما إذا كان مستخدم معين مخولاً استعمال محطة بعينها.

كان Binary Transmission في RFC 856 اختياراً عند الحاجة إلى ثمانية بتات. وكان Suppress-Go-Ahead في RFC 858 اختياراً عندما لا يلزم GA لمزامنة إرسال المحطة مع دور DSA. تلك الخيارات تغيّر قراءة البيانات وإيقاعها، لا هوية المتكلم ولا صلاحياته.

لا معنى لـACK من دون عنوان وسؤال قائم

جمع TNVIP قاموساً من النتائج بدلاً من خانة نجاح واحدة: ACK وERROR وBUSY وABORTED وPURGED وNOT-AVAILABLE وPROTOCOL-VIOLATION وUNKNOWN-COMMAND.

لكن حتى الكلمة نفسها تتغير وظيفتها بحسب السياق. على مسار الشاشة قد يعني ACK أن بيانات الشاشة عولجت جيداً، أو أن الخادم أقر طلب الانتقال إلى LOCAL. ويعني BUSY على الشاشة أن البيانات حُذفت لأن المحطة محلية. أما على مسار الطابعة، فيعني أن الطباعة السابقة لم تنته وأن الطلب الجديد حُذف. وREADY جواب عن استعلام حالة الطابعة، لا إقرار بإنجاز بيانات طباعة.

الرسالة indication المجهولة يمكن حذفها بلا جواب، إذ لم تفتح انتظاراً. أما request مجهول العنوان أو الأمر فيحتاج إلى رد مناسب لإغلاق الالتزام الذي أنشأه. لذلك لا يكفي سجل يحتفظ بكلمة الخطأ؛ لا بد من العنوان والنوع والطلب السابق.

وضع LOCAL كان رفضاً انتقائياً

قبل أن تدخل المحطة وضع LOCAL لإجراء اختبار أو تغيير إعدادات، يرسل العميل LOCAL-STATE. يقر الخادم الطلب ويعلق بيانات الشاشة والطابعة حتى تصله indication باسم ONLINE-STATE.

إذا وصلت بيانات من الخادم في أثناء LOCAL، يحذفها العميل. ويمكن أن يجيب عن request للشاشة بـBUSY. كل شيء في طبقة النقل قد يكون سليماً: الاتصال قائم، والعنوان صحيح، وEOR حاضر. مع ذلك تكون النتيجة المقصودة عدم التطبيق.

لم يسكت الوضع الاتصال كله. بقيت رسائل يرسلها جانب شاشة العميل، ورسائل عناوين أخرى، ممكنة. لذا فإن عبارة “المحطة مشغولة” تزيل التفاصيل الحاسمة: الاتجاه والجهاز والانتقال الذي أُقر.

إذن النسخ ليس تقرير الطباعة

قد تكون الطابعة مشتركة وتحت إدارة الخادم. لذلك كان على العميل، إذا أراد طباعة نسخة من الشاشة محلياً، أن يرسل COPY-REQ على المسار الثالث وينتظر السماح. فإذا وافق الخادم أرسل LOCAL-COPY.

كانت تلك رسالة response-and-request. أغلقت سؤال الإذن وفتحت سؤال النتيجة. بعد المحاولة ظل على العميل أن يعيد ACK أو ERROR أو BUSY أو ABORTED أو PURGED أو NOT-AVAILABLE.

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

صلاحية PURGE تنتهي عند الرد

عرّف كل مسار indication للمحو. إذا لم يكن الطلب قد أُقر، حاول المستقبل إيقاف المعالجة وأعاد PURGED. وإذا كان قد أجاب بالفعل، حذف رسالة المحو وتجاهلها.

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

تفيد فكرة Running-Code Primacy اللاحقة في قراءة هذا الحد، لا في اختلاق نية تاريخية: الوثيقة تسجل قاعدة، والتنفيذ يطبق انتقالاً، والجهاز يترك أثراً. لا ينوب سجل منها عن الآخر.

المصادر تصف آلية ولا تحصي واقعاً

تثبت RFC 1921 البنية المذكورة. وتسجل RFC 1576 ممارسات TN3270 المختلفة، فتحد موضوع مقال سابق ولا تجعل البروتوكولين شيئاً واحداً. لا تثبت الوثائق عدد منشآت TNVIP ولا مطابقة منتج Bull بعينه ولا حادثة فعلية ولا استعمالاً حالياً.

ولا تثبت مستخدماً أو تفويضاً أو نتيجة مضيف أو ورقة مطبوعة. تقدم Minimum Initial Specification, Localized Future Decision, and Voluntary Adoption مقياساً تحليلياً معاصراً: يكفي في الطبقة المشتركة ما يجعل الانتقال قابلاً للتحقق، ثم يبقى قرار الجهاز ودليل الأثر لدى من يستطيع تشغيلهما وملاحظتهما.

لم تجعل RFC 1921 الخطأ أقل ظهوراً حين أخرته. جعلته أكثر دقة. قالت إن الطلب الثاني فُقد، ثم انتظرت حتى تستطيع أن تقول لمن حدث ذلك من دون أن تفسد جواباً آخر.