مآخذ الويب. بعض الخبرة في التنمية والتشغيل. نحن تعديل العميل

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

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

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

بصفتي المختار ، استقرت على وحدة باستخدام مكتبات Apache. على وجه الخصوص ، هذه:

  • اباتشي-mime4j النواة 0.7.2.jar.
  • HttpClient وإصلاحه-4.2.1.jar.
  • httpcore-4.2.1.jar.
  • httpmime-4.2.1.jar.

ماذا يمكن أن يقال عن استخدامها؟ اشتهر برنامج Apache دائمًا بالموثوقية والتطور والكمال. عمل عميل Android بنجاح. لم يكن حجم ملف * .apk النهائي كبيرًا للغاية. لم تكن هناك شكاوى خاصة حول عمل هذه المكتبات. لكن الحياة دائما أكثر ذكاء منا. والوقت (وهذه الفترة حوالي أربع إلى خمس سنوات) يجعل التعديلات الخاصة بها. تمت كتابة التطبيق عندما كان هناك إصدار Android 4.2 - 4.4. وظهرت الحاجة إلى حلول جديدة بالفعل هذا العام ، عندما كانت الأجهزة التي تعمل بالإصدار 10 على قدم وساق.

تم إجراء التطوير في ذلك الوقت على Eclipse لنظام التشغيل Windows 7. أدى تحديث Android SDK إلى المستوى المرغوب فيه إلى امتلاء محرك الأقراص الصلبة 128 جيجابايت SSD الصغير. اضطررت إلى التبديل إلى Android Studio. علاوة على ذلك ، كان علي تغيير نظام التشغيل الأساسي. لقد حاولت تثبيت Ubuntu (لا أتذكر رقم الإصدار) واستخدم Studio بالفعل في هذه البيئة. ولكن مرة أخرى ، فشل ، Andriod Studio عنيد لا تريد تثبيت.

لماذا - نسي بالفعل. في النهاية ، بناءً على نصيحة الأصدقاء ، قام بتثبيت أحدث إصدار من Linux-Mint ، و ، ها ، ومجموعة الأدوات موجودة عليه دون أي شكاوى. ثم ما الذي حدث بالفعل ، على وجه التحديد بسبب وصف كل هذه التفاصيل ، أي روتين اختبارات الكتابة.

لذلك ، ما كان متوقعا في هذا tyagomotin؟ لنبدأ بحقيقة أن Apache من الموقع الرسمي قام بنسخ إصدارات أكثر حداثة من المكتبات المذكورة أعلاه. أضافهم إلى المشروع و ... وسقطت أخطاء التجميع. لقد مر الوقت ، تغيرت واجهات الفئة. لذلك كان لدي (بسبب ضيق الوقت لدراسة المكتبات الجديدة) للعودة إلى الإصدارات القديمة. لكن ...

ولكن مرة أخرى ، نحن لا نبحث عن طرق سهلة. فكرت ، لماذا أحتاج هذه المكتبات بالكامل؟ نصوص هذه الحزم هي. ماذا لو كنت تأخذ وسحب فقط الطبقات اللازمة منهم؟ علاوة على ذلك ، عند النظر في نصوص الوحدة النمطية للعمل مع مآخذ الويب ، يمكنك رؤية فئتين فقط من هذه المكتبات.

لذلك قمت بإنشاء مشروع جديد ، وبدأت بإضافة الفئات اللازمة. وفي النهاية اتضح أنه من أجل التجميع الناجح ، من الضروري سحب 32 فصلًا. وحتى الآن ، نعم ، نجح المشروع. كان كل شيء يتنفس. تم الاتصال بخدمة مأخذ توصيل الويب بنجاح. وسيكون كل شيء على ما يرام ، ولكن لاحظت الحدث التالي ، غير مفهومة بالنسبة لي. عند إغلاق الاتصال ، ألقت الوحدة المسؤولة عن الاتصال استثناءً:

java.io.EOFException
في java.io.DataInputStream.readByte (DataInputStream.java:77)
في com.example.wsci.HybiParser.start (HybiParser.java:112)
على com.example.wsci.WebSocketClient $ 1.run (WebSocketClient.java:144)
في java.lang.Thread.run (Thread.java:818)

كنت في حيرة. الخلط التالي. تم الاتصال بالخادم بنجاح. حزم جاء بنجاح وذهب. ولكن ، لماذا بالضبط الإغلاق يلقي استثناء؟ علاوة على ذلك ، كان كل شيء قياسي على الخادم. من الواضح ، في مكان ما في النص ، كان لدى العملاء بعض التافه الذي أثر على الإغلاق. علاوة على ذلك ، أظهرت النصوص هذه الميزة. وفقًا للفقرة 7.1.1 من المستند ، فإن الإغلاق من جانب العميل لا يقتصر فقط على استدعاء طريقة الإغلاق () ، ولكن أيضًا في تكوين وإرسال حزمة برمز العملية 8 (عملية الإغلاق). في هذه الحالة ، سيرسل الخادم حزمة الإغلاق ، وبعد ذلك يقوم العميل بإغلاق الاتصال. ولكن في حالتنا ، لم يلاحظ هذا التسلسل للمكالمات. لقد أطلقنا عليها فقط الوظيفة القريبة وهذا كل شيء. بشكل عام ، كان هناك شيء للتفكير فيه. وكلما قرأت ودرست نصوص هذه الوحدة مع محلل الرزم ، كلما أعجبتني أكثر ، كنت أكثر رغبة في إعادة كتابتها برؤيتي لهذا البروتوكول. في النهاية ، تقرر تنفيذ هذا "العمل الفذ".

ما الذي لم يناسب بالفعل ، ما سبب "الاحتجاج المدني" في هذه الوحدات؟ أولاً ، تنظيم التفاعل بين وحدة الاتصال المباشر مع الخادم ومحلل الحزمة. اتضح أن وحدة الاتصال تتفاعل مع الخادم ، وأنشأت محللًا قام بتمرير ارتباط إليه كمعلمة. نتيجة لذلك ، تم تفويض المحلل اللغوي سلطة اتخاذ القرارات بشأن أحداث الشبكة القادمة. في هذا الصدد ، طرح السؤال ، ولكن هل هو جيد؟ ألن يكون من الأفضل لو أن وحدة المعرب اللغوي ستفي بمهمتها ، وتعيد نتيجة عملها ، ولكن سيتم تنفيذ قرار التحكم في الأحداث بواسطة الكائن الذي أنشأ المحلل اللغوي؟ في هذه الحالة ، سيتم تحديد تسلسل هرمي صارم للتفاعل بين الكائنات. (هنا ، بالطبع ، يمكنك مناقشة ما هو أفضل - تسلسل هرمي أو شبكة ، ولكن بعد ذلك نبتعد عن الموضوع.)

الشيء الثاني الذي جعلني أرغب في إعادة كتابة كل شيء هو بنية المحلل اللغوي. يجب أن يفي هذا الكائن (الفئة) بوظيفتين رئيسيتين ، وهما: تكوين حزمة بيانات لإرسالها إلى الخادم وتحليل حزم البيانات المستلمة من الخادم. لذلك ، كانت هاتين الوظيفتين التي لم تتناسب ، إلى حد كبير. وها هو الشيء.

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

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

نتيجة لتقييم كل هذه الفروق الدقيقة ، تم تحديد المتطلبات التالية لتصميم الوحدات اللازمة:

  • يجب أن تكون الوحدات مستقلة عن مكتبات الجهات الخارجية ؛
  • يجب أن تكون الوحدات بسيطة وسهلة الاندماج في مشاريع أخرى ؛
  • يجب أن تكون الوحدات جاهزة للتوسع الوظيفي في المستقبل.

حسنًا ، وحتى لا يتم إلقاء اللوم على النقد المفرط للحل الجاهز السابق ، نضيف إلى هذا بالإضافة إلى ذلك أنه يمكن نقل جزء من المهام الجاهزة وغير الانتقائية بأمان إلى تطبيق جديد. حسنًا ، هذا كل شيء ، وكما قالوا في المؤتمر الثاني والعشرين للـ CPSU: "أهدافنا واضحة ، يتم تحديد المهام. للعمل ، أيها الرفاق! من أجل الانتصارات الجديدة للشيوعية! "

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

  • WebSocket بروتوكول 07 وحدة الثوابت العالمية ؛
  • فئة الاستثناء المساعد ؛
  • عميل مقبس الويب ؛
  • وحدة لتحليل الحزم من مستوى بروتوكول WebSocket 07.

في أول اثنين من وحدات ، وتنفيذ تافهة ، لا يوجد شيء للنظر. تطبق وحدة العميل التحكم في الاتصال بالخادم ، وأود أن أتطرق إلى النقاط التالية. وظيفة الاتصال المفتوحة لديها حلقة من الرؤوس القادمة من الخادم. هنا ، يتم بالفعل تنفيذ تحليل المفاتيح Sec-WebSocket-Accept ، وفي حالتنا ، يتم إجراء التحليل دون استخدام مكتبات Apache.

بعد ذلك ، انتبه إلى وظائف التحكم في حلقة الحزمة. التنفيذ تافه ، من خلال كائن التزامن.

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

لإكمال الوصف ، نلاحظ وظيفة إنهاء الاتصال بأمان. ويتم ذلك على النحو التالي. يتم إرسال حزمة إنهاء الاتصال إلى الخادم ويتم إنشاء متغير من فئة Runnable ، والذي يتم وضعه بعد ذلك في معالج قائمة الانتظار للتنفيذ من خلال وظيفة postDelayed ، واحدة من المعلمات منها التأخير في العملية بالميللي ثانية. في متغير Runnable ، تحتوي وظيفة التشغيل على سلسلة من المكالمات عندما ينتهي دفق البرنامج ويتم إغلاق الاتصال بالخادم. في حالة وصول حزمة استجابة الإغلاق في وقت مبكر ، يتم حذف هذا الموضع في قائمة المعالجة.

تحتوي الفئة التي تنفذ تحليل حزم WebSocket على طريقتين تتطلب الانتباه: تحليل نفسها وتشكيل حزمة للإرسال وفقًا للمعلمات ذات الصلة. عند التحليل ، يتم تخزين جميع الإشارات والبيانات من الحزمة المستلمة في متغيرات الفئة العامة. لماذا الجمهور؟ نعم ، للبساطة ، حتى لا تنشئ وظائف get / set إضافية لهم.

حسنا ، في الواقع ، عزيزي القارئ. يتم إرفاق الأرشيف مع مشروع Android Studio. لن أقدم أي مطالبات باستخدام هذه النصوص في مشاريعك. النقد البناء مقبول. أجب عن الأسئلة قدر الإمكان.

Source: https://habr.com/ru/post/ar478546/


All Articles