مقدمة
يقوم HTML5 WebSocket بتنفيذ اتصال ثنائي الاتجاه بين الخادم والمتصفح. الاتصالات ثنائية الاتجاه تجعل تطوير رسائل الخادم أكثر بساطة. الأكثر شيوعًا هي التواصل الفوري والتطبيقات التي تتطلب معلومات عالية الجودة في الوقت الفعلي. معظم رسائل الخادم السابقة تدفع تقنيات "الاقتراع" و "التوصيل الطويل" ، وكلاهما سيتحمل النفقات العامة على الخادم ، ولم يكن الأداء في الوقت الفعلي مرتفعًا بشكل خاص. سوف تتكبد تقنية WebSocket النفقات العامة الصغيرة فقط وهي مرتفعة بشكل خاص في الوقت الفعلي. لنبدأ بشرح كيفية استخدام تقنية WebSocket لتطوير غرف الدردشة. في هذا المثال ، يتم استخدام خادم TomCat7. يحتوي كل خادم على تطبيقات مختلفة من WebSocket ، لذلك لا يمكن تشغيل هذه المثيل إلا في خادم Tomcat. ومع ذلك ، أطلقت Spring WebSocket API ، والتي تتوافق مع تنفيذ كل خادم. يمكنك استشارة المعلومات ذات الصلة لفهمها. لن أقدمها هنا. الصورة التالية هي عرض غرفة الدردشة:
في هذا المثال ، يتم تنفيذ الدفع في الوقت الفعلي للرسائل ، ويتم تنفيذ الإخطارات عبر الإنترنت وغير المتصلة بمستخدمي الدردشة. دعنا نبدأ في شرح بالتفصيل كيفية تنفيذها.
معالجة الخلفية
يقوم Tomcat بتنفيذ WebSocket بشكل أساسي من خلال الاعتماد على فئة org.apache.catalina.websocket.messageinbound. هذه الفئة في {tomcat_home} /lib/catalina.jar ، لذلك عندما تتطور ، تحتاج إلى تقديم catalina.jar و tomcat-coyote.jar. الكود التالي يتعرض لعنوان Servlet للعميل:
حزمة com.ibcio ؛ استيراد javax.servlet.annotation.webservlet ؛ استيراد javax.servlet.http.httpservletrequest ؛ استيراد org.apache.catalina.websocket.streaminbound ؛ webservlet (urlpatterns = {"/message"}) // إذا كنت ترغب في استلام طلبات من المتصفح ws: // // ، يجب عليك تطبيق WebSocketServlet Class Public Class WebSocketSevetled org.apache.catalina.websocket.websocketservlet {private static static staticuidiid = 1l. static static int online_user_count = 1 ؛ السلسلة العامة getUser (طلب httpservletrequest) {return (سلسلة) request.getSession (). getAttribute ("user") ؛ } // على عكس servlets العادية ، يجب تنفيذ CreateWebsocketInbound ، ويتم تهيئة كائن اتصال WebSocket المخصص هنا Override StreamInbound CreateWebObocketInbound (سلسلة subprotocol ، httpservletrequest) {إرجاع WebSocketMoundMessageInbound (this.getuser (request)) ؛ }} هذا servlet يختلف إلى حد ما عن servlets العادية. يرث فئة WebSocketServlet ويحتاج إلى تجاوز طريقة CreateWebSocketInbound. يتم تعيين سمة المستخدم في الجلسة في هذه الفئة عندما يدخل المستخدم index.jsp ، ويسجل لقب المستخدم الحالي. فيما يلي رمز فئة WebSocketMessageInbound التي تم تنفيذها من قبل نفسك:
حزمة com.ibcio ؛ استيراد java.io.ioException ؛ استيراد java.nio.bytebuffer ؛ استيراد java.nio.charbuffer ؛ استيراد net.sf.json.jsonobject ؛ استيراد org.apache.catalina.websocket.messageInbound ؛ استيراد org.apache.catalina.websocket.wsoutBound ؛ الفئة العامة WebSocketMessageInbound يمتد MessageInbound {// اسم المستخدم للاتصال الحالي هو مستخدم سلسلة نهائية خاصة ؛ public WebSocketMessageInBound (string user) {this.user = user ؛ } السلسلة العامة getUser () {return this.user ؛ }. result.element ("type" ، "user_join") ؛ result.element ("المستخدم" ، this.user) ؛ . النتيجة = New JSonObject () ؛ result.element ("type" ، "get_online_user") ؛ result.element ("list" ، WebSocketMessageInboundPool.getOnlineUser ()) ؛ // أضف كائن الاتصال الحالي إلى WebSocketMessageInboundPool.AddMessageInbound (هذا) ؛ // أرسل قائمة المستخدمين الحالية عبر الإنترنت إلى اتصال WebSocketMessageInBoundPool.SendMessageTouser (this.user ، result.toString ()) ؛ } Override void onClose (int status) {// توجيه الحدث الختامي وإزالة الاتصال من تجمعات الاتصال webSocketMessageInboundPool.RemoVemessageInbound (هذا) ؛ JSonObject Result = New JSonObject () ؛ result.element ("type" ، "user_leave") ؛ result.element ("المستخدم" ، this.user) ؛ // أرسل الرسالة إلى المستخدم عبر الإنترنت بأن المستخدم الحالي يخرج webSocketMessageInBoundPool.sendMessage (result.toString ()) ؛ } override محمية void onBinaryMessage (رسالة bytebuffer) يرمي ioException {رمي جديد غير مدعوم ("رسالة ثنائية غير مدعومة.") ؛ } // يتم تشغيل الحدث عندما يرسل العميل رسالة إلى serverRide Override void ontextMessage (message charbuffer) يلقي ioException {// إرسال رسالة إلى جميع المستخدمين عبر الإنترنت webSocketMessageInBoundPool.SendMessage (message.tostring ()) ؛ }} ينفذ الرمز بشكل أساسي أساليب OnoPen و OnClose و OnTextMessage ، التي تتعامل مع المستخدمين عبر الإنترنت ، غير متصل ، وإرسال الرسائل على التوالي. هناك فئة WebSocketMessageInboundPool Connection Pool في هذه الفئة. يتم استخدام هذه الفئة لإدارة اتصالات المستخدمين عبر الإنترنت حاليًا. فيما يلي رمز هذه الفئة:
حزمة com.ibcio ؛ استيراد java.io.ioException ؛ استيراد java.nio.charbuffer ؛ استيراد java.util.hashmap ؛ استيراد java.util.map ؛ استيراد java.util.set ؛ الفئة العامة WebSocketMessageInboundPool {// حفظ حاوية الخريطة للاتصال الخريطة النهائية الثابتة الخاصة <String ، WebSocketMessageInbound> connections = new hashmap <string ، WebSocketMessageInbound> () ؛ // أضف اتصالًا إلى تجمع الاتصال العام addMessageInBound (WebSocketMessageInbound inbound) {// إضافة connection system.out.println ("المستخدم:" + inbound.getuser () + "Join ..") ؛ connections.put (inbound.getuser () ، inbound) ؛ } // احصل على جميع المستخدمين العامين على الإنترنت Set Set Set Set Set Set STATIC <STRING> GETONLINEUSER () {return connections.keyset () ؛ } removeMessageInBound ثابت عام (WebSocketMessageInBound inbound) {// إزالة نظام الاتصال. connections.remove (inbound.getuser ()) ؛ ) WebSocketMessageInBound Inbound = connects.get (user) ؛ if (inbound! = null) {inbound.getWsoutBound (). writeTextMessage (charbuffer.wrap (message)) ؛ }} catch (ioException e) {E.PrintStackTrace () ؛ }} // إرسال رسالة إلى جميع المستخدمين الفراغين الثابتين sendMessage (رسالة سلسلة) {try {set <string> keyset = connections.keyset () ؛ لـ (مفتاح السلسلة: keyset) {webSocketMessageInBound inbound = connects.get (key) ؛ if (inbound! = null) {system.out.println ("أرسل رسالة إلى المستخدم:" + KEY + "، محتوى الرسالة:" + رسالة) ؛ inbound.getWsoutBound (). WriteTextMessage (charbuffer.wrap (message)) ؛ }}} catch (ioException e) {E.PrintStackTrace () ؛ }}} عرض مكتب الاستقبال
الكود أعلاه هو رمز الواجهة الخلفية غرفة الدردشة ، والتي تتكون بشكل أساسي من 3 كائنات ، servlet ، كائن اتصال ، ومجموعة اتصال. فيما يلي رمز مكتب الاستقبال. ينفذ رمز مكتب الاستقبال بشكل أساسي الاتصال بالخادم ويعرض قائمة المستخدمين وقائمة المعلومات. يستخدم عرض مكتب الاستقبال إطار عمل Ext. يمكن للطلاب الذين ليسوا على دراية بـ EXT أن يكون لديهم فهم أولي لـ EXT. ما يلي هو رمز الفهرس. jsp:
<٪@ page language = "java" pageencoding = "utf-8" import = "com.ibcio.websocketMessageservlet" ٪> <٪ string user = (string) session.getAttribute ("user") ؛ if (user == null) {// قم بإنشاء لقب للمستخدم user = "Guest" + WebSocketMessageservlet.online_user_count ؛ WebSocketMessageservlet.online_user_count ++ ؛ Session.setAttribute ("user" ، user) ؛ } pagecontext.setAttribute ("user" ، user) ؛ ٪> <html> <head> <title> غرفة دردشة WebSocket </title> <!-تقديم ملفات CSS-> <Link Rel = "STYLESHEEN Rel = "STYLESHEET" type = "text/css" href = "css/websocket.css"/> <!- حزمة تطوير JS الخاصة بـ ext و webscoket المنفذة. -> <script type = "text/javaScript" src = "ext4/ext-all-debug.js"> </script> <script type = "text/javaScript" src = "websocket.js"> </script> <script type = "text/javascript"> var user = "$ {user}" ؛ </script> </head> <body> <h1> غرفة دردشة WebSocket </h1> <p> يتم دمج واجهة برمجة التطبيقات التي يوفرها معيار HTML5 مع إطار العميل الغني Extra لتنفيذ غرفة الدردشة ، والتي لها الخصائص التالية: </p> <ul style = "padding-left: 10px ؛" اتصال البيانات ، الذي يختلف عن التقنيات مثل الاقتراع والاتصال الطويل ، ويحفظ موارد الخادم </li> <li> مع مشاركة مع عرض الصفحة </li> <li> مستخدم عبر الإنترنت وإخطار غير متصل بالإنترنت </li> </ul> <div id = "websocket_button"> </div> </html> يتم التحكم بشكل رئيسي في عرض الصفحة في WebSocket.js. فيما يلي رمز websocket.jsd:
// تستخدم لعرض معلومات الدردشة الخاصة بالمستخدم Ext.define ('messageContainer' ، {extend: 'ext.view.view' ، trackover: true ، multiselect: false ، itemCls: 'l-im-message' ، itemSelector: 'liv.l-im-message' ، overitemcls: 'l-impessage "، elected-selective:" liM-messcted' الفائض: "Auto" ، الخلفية: "#FFF" ، TPL: ["<Div> لا تثق في التحويلات ، أو المكالمات الهاتفية غير المألوفة أثناء المحادثة. "<viv> {content} </viv> '،' </viv> '،' </tpl> '] ، الرسائل: [] ، initcomponent: function () {var me = this ؛ "المصدر"}) ؛ Message ['timestamp'] = ext.date.format (تاريخ جديد (رسالة ['timestamp']) ، 'h: i: s') ؛ if (message.from == user) {message.source = 'self' ؛ } آخر {message.source = 'Remote' ؛ } me.store.add (message) ؛ if (me.el.dom) {me.el.dom.scrolltop = me.el.dom.scrollheight ؛ }}}) ؛ ينفذ هذا الرمز بشكل أساسي الحاوية التي تعرض الرسالة. ما يلي هو الرمز الذي يبدأ التنفيذ بعد تحميل الصفحة:
ext.onReady (function () {// إنشاء مربع إدخال المستخدم var input = ext.create ('ext.form.field.htmleditor' ، {region: 'south' ، height: 120 ، enablefont: false ، enlabesourceedit: false ، enilealignments: false ، stanebs: دالة (e) {if ( ext.create ('ext.panel.panel' ، {المنطقة: "المركز" ، التصميم: "الحدود": [الإدخال ، الإخراج] ، الأزرار: [{text: 'send' ، handler}]}) ؛ WebSocket (encodeuri ('ws: // localhost: 8080/websocket/message')) ؛ } websocket.onclose = function () {// connection disconnected win.settitle (title + '(disconnected)') ؛ } // استقبال الرسائل websocket.onmessage = function (message) {var message = json.parse (message.data) ؛ // تلقي الرسائل المرسلة من قبل المستخدم if (message.type == 'message') {output.receive (message) ؛ } آخر إذا (message.type == 'get_online_user') {// الحصول على قائمة مستخدم عبر الإنترنت var root = OnlineUser.getRootNode () ؛ Ext.each (message.list ، function (user) {var node = root.createnode ({id: user ، text: user ، iconcls: 'user' ، leaf: true}) ؛ root.appendchild (node) ؛}) ؛ } آخر إذا (message.type == 'user_join') {// يذهب المستخدم عبر الإنترنت var root = OnlineUser.getRootNode () ؛ var user = message.user ؛ var node = root.createnode ({id: user ، النص: المستخدم ، iconcls: 'المستخدم' ، الورقة: true}) ؛ root.appendchild (العقدة) ؛ } if if (message.type == 'user_leave') {// يذهب المستخدم إلى وضع عدم الاتصال var root = OnlineUser.getRootNode () ؛ var user = message.user ؛ var node = root.findchild ('id' ، user) ؛ ROOT.REMOVECHILD (NODE) ؛ }}}}} ؛ // عبر الإنترنت TREE VAR ONLINEUSER = ext.create ('ext.tree.panel' ، {title: 'Online' ، rootvisible: false ، المنطقة: 'East' ، العرض: 150 ، الأسطر: false ، usearrows: true ، autoscroll: true ، split: true ، iconcls: 'user-online' ، store: ext.creat المستخدم '، الموسع: صحيح ، الأطفال: []}})}) ؛ var title = 'Welcome:' + user ؛ // عرض نافذة var win = ext.create ('ext.window.window' ، {title: title + '(غير متصل)' ، التصميم: 'الحدود' ، iconcls: 'win-win' ، minwidth: 650 ، minheight: 460 ، width: 650 ، animateTarget: 'WebSocket_button' Render: function () {initWebSocket () ؛ win.show () ؛ // إرسال وظيفة الرسالة send () {var message = {} ؛ if (websocket! = null) {if (input.getValue ()) {ext.apply (message ، {from: user ، content: input.getValue () ، timestamp: new date (). getTime () ، type: 'message'}) ؛ WebSocket.send (json.stringify (message)) ؛ //output.receive(message) ؛ input.setValue ('') ؛ }} آخر {ext.msg.alert ('tip' ، 'لقد تم قطع الاتصال ولا يمكنك إرسال الرسائل!') ؛ }}}}) ؛الرمز أعلاه هو الرمز الذي يتصل تلقائيًا بالخادم بعد تحميل الصفحة وإنشاء واجهة العرض.
يلاحظ
نقطتان للملاحظة: بعد الانتهاء من النشر ، يجب حذف catalina.jar و tomcat-coyote.jar في دليل LIB في دليل تطبيق Tomcat. على سبيل المثال ، دليل LIB للمشروع هو D:/Workspace/WebSocket/Webroot/Web-INF/LIB ، ودليل LIB للتطبيق المنشور هو D: /tools/apache-tomcat-7.0.32/webapps/websocket/web-inf/lib. ما عليك سوى حذف دليل lib لدليل النشر وتوصيل اثنين من الجرار. خلاف ذلك ، قد لا يتم تهيئة الخطأ. يتذكر.
إذا كان الاتصال لا يزال غير ممكن ، فيرجى تنزيل أحدث Tomcat. نسيت هذا الإصدار من TomCatcreatewebSocketInbound لا يحتوي على معلمة طلب. الرمز الحالي لديه هذه المعلمة. تأتي جميع إصدارات 7.0.3xx مع هذه المعلمة ، تذكر.
لخص
يعد استخدام WebSocket لتطوير Push Server مناسبًا للغاية. هذا تطبيق بسيط. في الواقع ، يمكن أن يجمع أيضًا بين WebRTC لتحقيق الدردشة المرئية والدردشة الصوتية.
مثال تنزيل
تنزيل العنوان: العرض التوضيحي
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.