-بيان ، ابتعد عن الناس الذين يميون الدماغ. جوهر هذه المدونة ليس بادئة IF-ELSE+ ، ولكن كيفية تحديد بروتوكول خاص من خلال إطار معالجة بروتوكول عنوان URL
الفرق بين URI وعنوان URL
URI (معرف الموارد الموحدة) معرف الموارد الموحد ؛ عنوان URL (موقع الموارد الموحدة) محدد موقع الموارد الموحد (أو محدد الموارد الموحد) ؛ URI هو مفهوم واسع نسبيا. عنوان URL هو نوع من URI ومجموعة فرعية من آلية تسمية URI. يمكن القول أن URI مجردة ، والاستخدام المحدد لعناوين URL لتحديد الموارد. يشير URI عمومًا إلى مسار الموارد المادية ، ولكن معرف الموارد المعين في النظام بأكمله. عناوين URL هي سلاسل مستخدمة على الإنترنت لوصف موارد المعلومات ، وتستخدم بشكل رئيسي على مختلف برامج عملاء WWW وبرامج الخادم. يمكن استخدام عناوين URL استخدام تنسيق موحد لوصف موارد المعلومات المختلفة ، بما في ذلك الملفات وعناوين الخادم والأدلة ، إلخ.
1. دعونا نولد المقدمة
لقد اعتدنا على HTTP
url url = url جديد (http://www.apptest.com:8080/test/ios.php) ؛
يجب أن نعتاد على ذلك أيضًا
بالطبع ، نحتاج أيضًا إلى التعود على عنوان URL.
"https" ، "ftp" ، "mailto" ، "telnet" ، "file" ، "ldap" ، "gopher" ، "jdbc" ، "rmi" ، "jndi" ،
url url = url جديد ("Oschina: //www.apptest.com: 8080/test/ios.php") ؛إذا لم تكن معتادًا على ذلك ، فسيحدث الاستثناءات التالية دائمًا
java.net.malformedurlexception: بروتوكول غير معروف
عند استخدام Ajax في متصفحات Android ، لن يتم دعم البروتوكولات غير المحددة.
2. فهم البروتوكولات المخصصة
البروتوكول: في عالم البرمجة ، يعد البروتوكول نفسه مجموعة من قواعد قيود الإدخال/OUPUT. لذلك ، يجب أن يدور بروتوكولنا الدقيق حول الإدخال/الإخراج ، بحيث يمكن تسمية البروتوكول هنا ببروتوكول الإدخال/الإخراج.
بادئ الاتفاق: طلب
مستجيب البروتوكول: الاستجابة
شروط إنشاء الاتفاقية هي: الطلب والاستجابة تعترف بنفس المجموعة من الاتفاقات والتواصل وفقًا لقيود الاتفاقية.
3. العلاقة بين البروتوكول المخصص وعنوان URL
في Java ، هل تتطلب بروتوكولات مخصصة عناوين URL؟
الجواب لا.
في الواقع ، حول I/O ، تعاريف القواعد لدينا هي تماما في أيدينا. لا يقول أن الأرض لن تستدير بعد مغادرة عنوان URL ، وسيتم تدمير جافا.
لماذا تخصيص البروتوكول باستخدام فئات URL؟
الجواب هو أن عنوان URL هو إطار معالجة اتصال البروتوكول الناضج.
بروتوكول عنوان URL المخصص المذكور هنا هو في الأساس أكثر حول توسيع البروتوكول من خلال القواعد الحالية.
4.
نحن نعلم أن البروتوكولات المخصصة تتطلب الاستجابة والطلب ، ويحتاج كلا الطرفين إلى فهم اتفاق بعضهما البعض تمامًا. للراحة هنا ، نستخدم خادم بروتوكول HTTP كاستجابة.
هنا نستخدم NGNIX Server + PHP + fastcgi لبناء الاستجابة ، ورمز النشر كما يلي
1. تحديد الاستجابة
<؟ php $ raw_post_data = file_get_contents ('php: // input' ، 'r') ؛ Echo "-------/$ _ post ------------------/n <br/>" ؛ صدى var_dump ($ _ post). "/n" ؛ ECHO "------- PHP: // input -------------/n <br/>" ؛ echo $ raw_post_data. "/n <br/>" ؛ $ rs = json_encode ($ _ server) ؛ file_put_contents ('text.html' ، $ rs) ؛ echo '写入成功' ؛2. تحديد الطلب
2.1 تنفيذ مصنع urlstreamhandlerfactory ، يستخدم بشكل رئيسي لإنشاء معالجات البروتوكول
الطبقة العامة echorlstreamhandlerfactory تنفذ urlstreamhandlerfactory {urlstreamhandler public createurlstreamhandler (protocol string) {// تخصيص طلبات المخطط المختلفة من خلال التحويل هنا. بالطبع ، يعتقد الناس الذين يميلون إلى الدماغ أن هذا هو الكود الأساسي. عنوان URL هو إطار معالجة البروتوكول. إذا كان If-Else هو الأساس ، فهل ستضيء Oracle إذا (protocol.equals ("echo") || protocol.equals ("Oschina")) {إرجاع echourlstreamhandler () // Instantiate معالج معالجة البروتوكول} إرجاع فارغ ؛ }}2.2 تنفيذ urlstreamhandler ، الوظيفة الرئيسية هي إنشاء الموصل المقابل للبروتوكول
الطبقة العامة echourlstreamhandler يمتد urlstreamhandler {OverRideProtected urlConnection OpenConnection (url u) يلقي ioException {return echourlconnection (u) ؛ // يمكننا أيضًا إجراء التحويل المقابل هنا}} 2.3 تنفيذ URLConnection ، وهو تخصيص قواعد اتصال البروتوكول. هنا نستخدم بروتوكول HTTP كقواعد اتصال. نحن هنا نقلد طلبات بروتوكول HTTP
(ما يلي هو الرمز الأساسي. بروتوكول HTTP مستعار هنا. بالطبع ، يمكنك التفاعل مع بروتوكولات مختلفة باستخدام WebSocket و SMTP و FTP ، بدلاً من بادئة URL IF-ELSE+التي يطلب مني الأشخاص الذين يميلون إلى الدماغ أن أعترف )
الطبقة العامة echourlconnection يمتد urlConnection {private socket connection = null ؛ public static int int default_port = 80 ؛ echourlconnection العامة (url url) {super (url) ؛ getOutputStream () يلقي ioException {if (! connect) {connect () ؛} إرجاع الاتصال. default_port ؛ هذا. هذا. connection.setreuseaddress (صحيح) ؛ // يشير إلى مهلة الانتظار عند تلقي البيانات ، بالمللي ثانية .. القيمة الافتراضية هي 0 ، مما يعني أنه سيكون هناك انتظار لا حصر له ولن يقوم أبدًا بتهمة التوصيل // عند قراءة البيانات من خلال دفق المقبس ، إذا لم يكن هناك أي بيانات ، فسيكون ذلك ينتظر // البيانات مرة أخرى this.connection.setsotimeout (30000) ؛ // تشير إلى ما إذا كان المقبس الأساسي مغلقًا على الفور // عند إغلاق المقبس ، سيتم تأخير المقبس الأساسي بمقدار 5 ثوان ثم يغلق مرة أخرى. بعد 5 ثوان ، سيتم التخلص من جميع البيانات المتبقية التي لم يتم إرسالها. بشكل افتراضي ، إذا تم تنفيذ طريقة socket.close () ، فسيتم إرجاع الطريقة على الفور ، ولكن المقبس الأساسي لا يتم إغلاقه على الفور // ، فسيؤخر ذلك لفترة من الوقت حتى يتم إرسال جميع البيانات المتبقية ، وسيتم إغلاق المقبس حقًا إلى الشبكة ، وينفصل عن الشبكة/الإرسال/عندما يكتب البرنامج البيانات من خلال دفق الإخراج ، فإن ذلك يعني أن البرنامج الفرعي للبيانات. نصائح: عندما يغلق البرنامج المقبس ، فمن المحتمل أن يتم نقل مجموعة البيانات على الشبكة ولم تصل إلى نصائح المتلقي //: "البيانات المتبقية المتبقية" المذكورة هنا تشير إلى هذه البيانات التي لا تزال تنتقل على الشبكة ، ولم يتم استلامها من قبل المتلقي. this.connection.setsendbuffersize (1024) ؛ // يشير إلى حجم المخزن المؤقت حيث يتم استلام البيانات this.connection.setReceiveBuffersize (1024) ؛ لا تنقل البيانات إلى بعضها البعض)؟ TRUE هو نعم // قيمتها الافتراضية خاطئة ، مما يعني أن TCP لن تراقب ما إذا كان الاتصال صالحًا ، وقد يكون العملاء غير النشطين موجودين بشكل دائم دون إشعار بأن الخادم قد تعطل هذا. // يشير إلى ما إذا كان يدعم إرسال بايت واحد من بيانات الطوارئ TCP. يتم استخدام Socket.SendurgentData (البيانات) لإرسال بايت واحد من بيانات الطوارئ TCP // إنه افتراضي إلى خطأ ، أي أن المتلقي لا يقوم بأي معالجة عند تلقي بيانات الطوارئ ويتجاهلها مباشرة. إذا أراد المستخدم إرسال بيانات الطوارئ ، فيجب تعيينه على True // بعد الإعداد إلى True ، فسيقوم جهاز الاستقبال بوضع بيانات الطوارئ المستلمة في نفس قائمة الانتظار مثل البيانات العادية this.connection.setoobinline (true) ؛ // يتم استخدام هذه الطريقة لتعيين نوع الخدمة. تطلب التعليمات البرمجية التالية موثوقية عالية وحد أدنى لخدمة نقل التأخير (بت أو عمليات 0x04 و 0x10) // فئة المقبس تستخدم 4 أعداد صحيحة لتمثيل نوع الخدمة // 0x02: التكلفة المنخفضة (البت قبل الأخير من Binary هو 1) // 0x10: الحد الأدنى للتأخير (الجزء الخامس قبل الأخير من الثنائي هو 1) هذا. latency-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- url.getPath () + "http/1.1 /r/n") ؛//if(url.getport()<0 || url.getport ()> 65536) {sb.append ("المضيف:") Host ()). إلحاق (":"). إلحاق (url.getport ()) 22 أبريل 2016 13:17:35 gmt/r/n ") ؛ sb.append (" vary: accept-encoding/r/n ") ؛ sb.append (" نوع المحتوى: التطبيق/x-www-form-urlencoded ، charset = utf-8/r/n ") ؛ sb.append ( ") .append (" name = Zhangsan & Password = 123456 ".GetBytes (" UTF-8 ") difnonnect () يلقي ioException {if (connected) {this.connection.close () ؛ this.connected = false ؛}}} هنا ، تم الانتهاء من تعريف البروتوكول.
رمز الاختبار الخاص بنا كما يلي
حاول الاتصال بـ Oschina: // localhost: 8080/test/ios.php
url.setUrlStreamHandlerFactory (echorlstreamhandlerfactory ()) connection = (echorlConnection) url.openconnection () ؛ connection.setDooutput (true) ؛ connection.setDoInput (true) ؛ printWriter pw = new printWriter (new OutputStreamWriter (connection.getOutputStream ())) ؛ pw.write ("name = Zhangsan & Password = 123456") ؛ pw.flush () ؛ دفق inputStream = connection.getInputStream () ؛ int len = -1 ؛ Byte [] buf = new byte [256] ؛ بينما ((len = dream.read (buf ، 0 ، 256))>-1) {String Line = new String (buf ، 0 ، len) ؛ if (line.endswith ("/r/n0/r/n/r/n") && len <256) {// يقوم الخادم بإرجاع ترميز ترميز مستقل ،/r/n0/r/n/r/n يعني أن القراءة قد انتهت ، chunked التشفير التحليل: http://dbscx.iteye.com/blog/830644 line.length ()-"/r/n0/r/n/r/n" .length ()) ؛ system.out.println (line) ؛ استراحة؛ } آخر {system.out.println (line) ؛ }} pw.close () ؛ Stream.close () ؛نتائج التشغيل
توضح النتيجة أن البروتوكول قد تم تعريفه بالفعل بنجاح
بالطبع ، لا يفي تحليل البيانات المذكورة أعلاه بمتطلباتنا لأنه يتم تصنيف معلومات الترميز. كيفية تحليلها تلبي المتطلبات ، يرجى الانتقال :
HTTP تشفير البيانات وفرص التحليل خوارزمية التحليل
5. لاحقًا ، محلل صغير مخصص
يتم توفير ContentHandlerFactory في Java لتحليل minetype. نصيح محللنا هنا. بالطبع ، يوفر JDK أكثر وفرة. ما نفعله هنا هو تلبية الاحتياجات الخاصة.
الطبقة العامة echocontentHandler يمتد contentHandler {public object getContent (urlConnection Connection) يلقي ioException {inputStream in = connection.getInputStream () ؛ BufferedReader Br = new BufferReader (urlconte) throwse (urowse) {inputStream in = connect.getInputStream () ؛ for (int i = 0 ؛ i <classes.length ؛ i ++) {if (classes [i] == inputstream.class) return in ؛ else (classes [i] == string.class) return getContent (connect) ؛} return ؛}}}}}}}}}}}}الاستخدام بسيط للغاية
urlconnection.setContentHandlerFactory (echocontentHandlerFactory جديد ()) ؛