يتم استخدام وظيفة دفع الرسائل بواسطة WebSocket و Java بواسطة Server TomCat7.0. تعتبر بعض الأشياء بنفسك ، ولا أعرف ما إذا كانت مناسبة أو غير ملائمة. أرجوك سامحني وأشر إليهم.
بعبارات بسيطة ، يمكن للعميل إرسال رسائل إلى العميل B ، ولكن هناك العديد من الأماكن التي يمكن توسيعها.
على سبيل المثال
1. إذا بعد الانضمام إلى قاعدة البيانات ، عندما يرسل A الرسالة ، فإن العميل B ليس عبر الإنترنت ، فسيقوم الخادم بتخزين الرسالة في قاعدة البيانات. بعد أن يكون العميل B متصلاً بالإنترنت ، سيتم استرداد الرسالة وإرسالها إلى العميل ب.
2. يمكن للخادم أيضًا إرسال رسائل إلى أي عميل.
لقطة شاشة لتأثير تشغيل البرنامج كما يلي (تم اختباره تحت Chrome و Sogou و Firefox): سيتم إعطاء الكود في النهاية
أولاً ، نفتح متصفحًا وعرضنا لإدخال اسمك. هنا أدخل SOAR
عند فتح المتصفح الثاني ، أدخل بيل هنا
هذا إذا أرسلت Hello Bill ، فأنا أرتفع إلى فاتورة ، انقر فوق إرسال
يمكنك رؤيته على متصفح آخر
WebSocket
1. ما هو WebSocket؟
WebSocket هي تقنية يتم إنشاؤها لحل التواصل في الوقت الفعلي بين العملاء والخوادم. يتمثل الجوهر في إنشاء اتصال TCP لتبادل البيانات بعد المصافحة من خلال بروتوكول HTTP/HTTPS.
بعد ذلك ، يتواصل الخادم والعميل في الوقت الفعلي من خلال اتصال TCP هذا.
2. مزايا WebSocket
في الماضي ، قمنا بتنفيذ تقنية الدفع ، باستخدام الاقتراع. في الفاصل الزمني المميز ، يصدر المستعرض تلقائيًا طلبًا وسحب رسائل الخادم بنشاط. في هذه الحالة ، نحتاج إلى إرسال طلبات باستمرار إلى الخادم. ومع ذلك ، فإن رأس طلب HTTP طويل جدًا ، وقد تكون البيانات الموجودة فيه مجرد قيمة صغيرة ، والتي ستشغل الكثير من موارد النطاق الترددي والخادم. وسوف تستهلك الكثير من موارد النطاق الترددي والخادم.
أعظم شيء في واجهة برمجة تطبيقات WebSocket هو أن الخادم والعميل يمكنه دفع المعلومات إلى بعضهما البعض في أي وقت خلال نطاق زمني معين. بعد إنشاء الاتصال ، يمكن للخادم نقل البيانات بنشاط إلى العميل.
بالإضافة إلى ذلك ، فإن معلومات الرأس المتبادلة بين الخادم والعميل صغير جدًا.
لا يقتصر WebSocket على الاتصال في وضع AJAX (أو XHR) ، لأن تقنية AJAX تتطلب من العملاء بدء طلبات ، بينما يمكن لخوادم WebSocket والعملاء دفع المعلومات إلى بعضهم البعض ؛
للحصول على مقدمة مفصلة عن رسائل Ajax و Comet و WebSocket و WebSocket ، يمكنك الرجوع إلى http://www.shaoqun.com/a/54588.aspx تصميم الويب] Ajax و Comet و WebSocket.
إذا كان لدي وقت في المستقبل ، فسوف أكتبها.
3. كيفية استخدام WebSocket
عميل
في متصفح يدعم WebSocket ، بعد إنشاء المقبس. يمكنك الاستجابة للمآخذ من خلال أربعة أحداث: OnoPen ، OnMessage ، و Onclose ، أي onerror.
مثال بسيط
var ws = new WebSocket (ws: // localhost: 8080) ؛ ws.Onopen = function () {console.log (open) ؛ ws.send (hello) ؛} ؛ ws.onmessage = function (evt) {console.log (evt.data)} ؛ ws.onclose = function (evt) {console.log (websocketClosed!) ؛} ؛ ws.onerror = function (evt)1.var ws = WebSocket جديد (ws: // localhost: 8080) ؛
للتقدم بطلب للحصول على كائن WebSocket ، فإن المعلمات هي عنوان الخادم الذي يجب توصيله. تمامًا مثل بروتوكول HTTP ، يبدأ عنوان URL لبروتوكول WebSocket بـ WS: // ، ويبدأ بروتوكول WebSocket الآمن بـ WSS: //.
ws.send (مرحبا) ؛
تستخدم لإرسال الرسائل إلى الخادم
2.ws.onopen = function () {console.log (open)} ؛
عند إنشاء WebSocket بنجاح ، سيتم تشغيل حدث OnoPen
3.ws.onmessage = function (evt) {console.log (evt.data)} ؛
عندما يتلقى العميل رسالة أرسلها الخادم ، سيتم تشغيل حدث OnMessage. تحتوي المعلمة evt.data على البيانات التي يتم نقلها بواسطة الخادم.
4.ws.onclose = function (evt) {console.log (WebSocketClosed!) ؛ } ؛
عندما يتلقى العميل طلبًا لإغلاق الاتصال الذي أرسله الخادم ، يتم تشغيل حدث OnClose
5.ws.onerror = function (evt) {console.log (WebSocketerror!) ؛ } ؛
إذا فشل الاتصال والمعالجة والاستلام وإرسال البيانات ، فسيتم تشغيل حدث ONERROR
يمكننا أن نرى أن جميع العمليات يتم تشغيلها بالأحداث ، بحيث لن تمنع واجهة المستخدم ، مما يتيح لاستخدام واجهة المستخدم أن يكون لديك وقت استجابة أسرع وتجربة مستخدم أفضل.
جانب الخادم
في الوقت الحاضر ، هناك العديد من برامج الخادم التي تدعم WebSocket ، مثل Node.js ، Jetty ، Tomcat ، إلخ.
أنا هنا أستخدم Tomat 7.0 و Eclipse4.2
Tomcat ، استخدم WebSocket أولاً لاستيراد الجرة ذات الصلة
توجد الفئات المتعلقة بـ WebSocket التي توفرها TomCat7 في الحزمة org.apache.catalina.websocket (تنفيذ الحزمة org.apache.catalina.websocket موجودة في الملف catalina.jar
هنا نحن فقط استيراد كل tomcat
في مسار البناء-تكوين مسار الإنشاء-> المكتبة-> إضافة مكتبة-> وقت تشغيل الخادم-> Apache Tomcat V7.0
صورة
أيضا ، استيراد الحزم التالية
استيراد org.apache.catalina.websocket.messageInbound ؛
استيراد org.apache.catalina.websocket.streaminbound ؛
استيراد org.apache.catalina.websocket.wsoutBound ؛
استيراد org.apache.catalina.websocket.websocketservlet ؛
نحن بحاجة إلى فصلين
يتم استخدام أول واحد للتعامل مع طلبات WebSocket
يتم استخدام المجموعة الثانية للتعامل مع كل مهمة WebSocket محددة
الفئة الأولى
يمتد SocketServer من الطبقة العامة websocketservlet {
خاص ثابت نهائي طويل المسبانيويد = 1L ؛
// ...
@تجاوز
StreamInbound Creative CreateWebsocketInbound (String Arg0 ،
httpservletrequest arg1) {
// TODO METHOTION METTOD COBS
إرجاع chatwebsocket جديد (المستخدمين) ؛
}
}
يرث هذا servlet من WebSocketServlet وينفذ طريقة CreateWebsocketInbound. هذه الطريقة تُرجع مثيلًا للفئة الثانية.
الفئة الثانية
يمتد ChatWebsocket من الفئة العامة MessageInbound {
@تجاوز
void ontextMessage المحمي (رسالة charbuffer) يلقي ioException {
}
@تجاوز
الفراغ المحمي OnoPen (WsoutBound Outbound) {
}
@تجاوز
void onclose (int state) {
}
@تجاوز
void onBinaryMessage المحمي (bytebuffer arg0) يلقي ioException {
}
// الباقي مجرد القليل
}
void ontextMessage المحمي (رسالة charbuffer) يلقي ioException {}
استجابة الرسائل النصية
void onBinaryMessage المحمي (Bytebuffer Arg0) يلقي ioException {}
استجابة الرسالة الثنائية
باطل محمي OnoPen (WsoutBound Outbound) {}
الأحداث الناتجة عن إنشاء اتصال
void onclose المحمي (الحالة int) {}
تم إطلاق الأحداث عند إغلاق الاتصال
4. رمز البرنامج
جزء HTML
<! doctype html>
<html>
<head>
<meta charset = utf-8>
<script type = text/javaScript src = js/jquery.js> </script>
<script type = text/javaScript src = js/socket.js> </script>
<title> Unted Document </title>
</head>
<لغة البرنامج النصي = javaScript>
</script>
<body>
<griding>
<tr>
<td> الرسالة </td>
<td> <type type = text id = message> </td>
</r>
<tr>
<td> الاسم </td>
<td> <input type = text id = othername> </td>
</r>
<tr>
<td> <input id = sendbutton type = button value = send onClick = انقر فوق upabled = true>
</input> </td>
</r>
</table>
<script>
</script>
</body>
</html>
جزء من جزء (لا يوجد تفسير عن جزء jQuery)
var username = window.prompt (أدخل اسمك :) ؛
document.write (مرحبًا <p id =/username/>+اسم المستخدم+</p>) ؛
if (! window.websocket && window.mozwebsocket)
window.websocket = window.mozwebsocket ؛
إذا (! window.websocket)
تنبيه (لا دعم) ؛
var ws ؛
$ (وثيقة). ready (function () {
$ (#sendButton) .ATTR (معطل ، خطأ) ؛
$ (#sendbutton) .click (sendMessage) ؛
StartWebSocket () ؛
})
وظيفة sendMessage ()
{
var othersName = $ (#othername) .val () ؛
var msg = msg/t+username+_+othername+_+$ (#message) .val () ؛
إرسال (msg) ؛
}
إرسال الوظيفة (البيانات)
{
console.log (إرسال:+بيانات) ؛
ws.send (البيانات) ؛
}
وظيفة startWebSocket ()
{
WS = WebSocket جديد (ws: // + location.host +/WebSocket/SocketServer) ؛
ws.onopen = function () {
console.log (النجاح المفتوح) ؛
$ (#sendButton) .ATTR (معطل ، خطأ) ؛
} ؛
ws.onmessage = وظيفة (حدث)
{
console.log (تلقي:+event.data) ؛
handledata (event.data) ؛
} ؛
ws.onclose = وظيفة (حدث) {
console.log (تم إغلاق Socket العميل ، الحدث) ؛
} ؛
}
وظيفة handledata (البيانات)
{
var vals = data.split (/t) ؛
var msgtype = vals [0] ؛
التبديل (msgtype)
{
اسم الحالة:
var msg = vals [1] ؛
var mes = name+/t+msg+_+اسم المستخدم ؛
إرسال (mes) ؛
استراحة؛
حالة MSG:
var val2s = vals [1] .Split (_) ؛
var from = val2s [0] ؛
رسالة var = val2s [2] ؛
تنبيه (من+:+رسالة) ؛
استراحة؛
تقصير:
استراحة؛
}
}
جزء جافا
استيراد java.io.ioException ؛
استيراد java.nio.bytebuffer ؛
استيراد java.nio.charbuffer ؛
استيراد javax.servlet.http.httpservletrequest ؛
استيراد java.util.set ؛
استيراد java.util.concurrent.copyonwritearrayset ؛
استيراد org.apache.catalina.websocket.messageInbound ؛
استيراد org.apache.catalina.websocket.streaminbound ؛
استيراد org.apache.catalina.websocket.wsoutBound ؛
استيراد org.apache.catalina.websocket.websocketservlet ؛
يمتد SocketServer من الطبقة العامة websocketservlet {
خاص ثابت نهائي طويل المسبانيويد = 1L ؛
المجموعة النهائية العامة <ThatWebSocket> المستخدمين = New CopleRwriteArrayset <ThatWebSocket> () ؛
مستمر ثابت عام = 1 ؛
@تجاوز
StreamInbound Creative CreateWebsocketInbound (String Arg0 ،
httpservletrequest arg1) {
// TODO METHOTION METTOD COBS
إرجاع chatwebsocket جديد (المستخدمين) ؛
}
يمتد ChatWebsocket من الفئة العامة MessageInbound {
اسم المستخدم الخاص بالسلسلة الخاصة ؛
مجموعة خاصة <ThatWebSocket> = New CopyOnWriteArrayset <ThatWebSocket> () ؛؛
chatwebsocket العامة () {
}
chatwebsocket العامة (تعيين <ThatWebSocket> مستخدمين) {
this.users = المستخدمين ؛
}
@تجاوز
void ontextMessage المحمي (رسالة charbuffer) يلقي ioException {
// ما تمت معالجته هنا هو بيانات النص
}
public void onMessage (بيانات السلسلة) {
String [] Val1 = data.split (// t) ؛
if (val1 [0] .equals (name))
{
String [] Val2 = Val1 [1] .Split (_) ؛
لـ (atherwebsocket user: user) {
if (user.username.equals (val2 [0])) {
user.username = val2 [1] ؛
}
}
}
آخر إذا (Val1 [0] .equals (msg))
{
String [] Val2 = Val1 [1] .Split (_) ؛
لـ (atherwebsocket user: user) {
if (user.username.equals (val2 [1])) {
يحاول {
Tempafer Temp = Charbuffer.wrap (data) ؛
user.getWsoutBound (). writeTextMessage (temp) ؛
} catch (ioException e) {
// TODO AUTO CATCH BLOCK
E.PrintStackTrace () ؛
}
}
}
}
آخر
{
system.out.println (خطأ) ؛
}
}
@تجاوز
الفراغ المحمي OnoPen (WsoutBound Outbound) {
// this.connection = connection ؛
this.userName = # + string.valueof (usernumber) ؛
usernumber ++ ؛
يحاول {
رسالة سلسلة = اسم + /t + this.username ؛
charbuffer buffer = charbuffer.wrap (message) ؛
this.getWsoutBound (). WriteTextMessage (Buffer) ؛
} catch (ioException e) {
// TODO AUTO CATCH BLOCK
E.PrintStackTrace () ؛
}
user.add (هذا) ؛
}
@تجاوز
void onclose (int state) {
users.remove (هذا) ؛
}
@تجاوز
void onBinaryMessage المحمي (bytebuffer arg0) يلقي ioException {
}
}
}
يشرح
فكرتي هنا
1 عند الوصول ، يحتاج كل مستخدم أولاً إلى إدخال اسمه أو اسمها ، ثم إرسال طلب اتصال إلى الخادم.
2 بعد أن يقبل الخادم طلب اتصال العميل ، سيفعل chatwebsocket جديد (المستخدمين) ؛ لمعالجة هذا الطلب وإضافته إلى قائمة المستخدمين عبر الإنترنت. في هذا الوقت ، لا يعرف الخادم اسم العميل بعد. سوف يفترض اسم هذا المستخدم ، #1 ، وسيقوم الخادم بإرسال اسم + /T + #1 إلى العميل ، ما اسمك؟
3 عندما يتلقى العميل هذه الرسالة ، سيعرف أن الخادم يسأل نفسه عن اسمه ، لذلك سيرسل العميل اسم+/t+#1+_+اسمه الخاص بالخادم (اسمي xxx)
4 بعد تلقي هذه الرسالة ، يبحث الخادم في قائمة المستخدمين عبر الإنترنت حاليًا استنادًا إلى رقم 1 ، ويحل محل #1 باسم العميل ، بحيث يعرف الخادم اسم العميل.
5 عندما يغادر العميل ، سيؤدي الخادم إلى تشغيل حدث OnClose ، وسيقوم الخادم بإزالة المستخدم الحالي من القائمة عبر الإنترنت.
استخدم الصور لرسم شيء مثل هذا (رسم سيئ ، -_- !!)
شفرة
JS
WS = WebSocket جديد (ws: // + location.host +/WebSocket/SocketServer) ؛
الاتصال بالخادم
جافا
StreamInbound Creative CreateWebsocketInbound (String Arg0 ،
httpservletrequest arg1) {
// TODO METHOTION METTOD COBS
إرجاع chatwebsocket جديد (المستخدمين) ؛
}
قم بإنشاء chatwebsocket للتعامل مع هذا الطلب وإطلاق حدث OnoPen لكائن ChatWebsocket
@تجاوز
الفراغ المحمي OnoPen (WsoutBound Outbound) {
// this.connection = connection ؛
this.userName = # + string.valueof (usernumber) ؛
usernumber ++ ؛
يحاول {
رسالة سلسلة = اسم + /t + this.username ؛
charbuffer buffer = charbuffer.wrap (message) ؛
this.getWsoutBound (). WriteTextMessage (Buffer) ؛
} catch (ioException e) {
// TODO AUTO CATCH BLOCK
E.PrintStackTrace () ؛
}
user.add (هذا) ؛
}
بافتراض اسم لهذا العميل ، وإرسال اسم الاسم المفترض+/T+ إلى العميل ، وإضافة العميل إلى قائمة العميل المتصل حاليًا
JS
وظيفة handledata (البيانات)
{
var vals = data.split (/t) ؛
var msgtype = vals [0] ؛
التبديل (msgtype)
{
اسم الحالة:
var msg = vals [1] ؛
var mes = name+/t+msg+_+اسم المستخدم ؛
إرسال (mes) ؛
استراحة؛
// ………
}
}
قبول ومعالجة الرسالة التي أرسلها الخادم ، وابحث أن الخادم سألها عن اسمه ، لذلك أرسل اسم+/t+الاسم المفترض+_+إلى الخادم.
جافا
public void onMessage (بيانات السلسلة) {
String [] Val1 = data.split (// t) ؛
if (val1 [0] .equals (name))
{
String [] Val2 = Val1 [1] .Split (_) ؛
لـ (atherwebsocket user: user) {
if (user.username.equals (val2 [0])) {
user.username = val2 [1] ؛
}
}
}
// ………
}
قم بمعالجة الرسالة التي أرسلها العميل وقبولها ، واكتشف أن العميل رد على اسمه ، لذلك ابحث في قائمة العميل المتصل حاليًا بناءً على الاسم المفترض مسبقًا ، وقلب اسم مستعار إلى الاسم الحقيقي
JS
وظيفة sendMessage ()
{
var othersName = $ (#othername) .val () ؛
var msg = msg/t+username+_+othername+_+$ (#message) .val () ؛
إرسال (msg) ؛
}
يبدأ العميل محادثة مع شخص آخر ، وتنسيق الرسائل هو: MSG+اسمه الخاص+_+الاسم المعاكس+_+
جافا
public void onMessage (بيانات السلسلة) {
/// …………
آخر إذا (Val1 [0] .equals (msg))
{
String [] Val2 = Val1 [1] .Split (_) ؛
لـ (atherwebsocket user: user) {
if (user.username.equals (val2 [1])) {
يحاول {
Tempafer Temp = Charbuffer.wrap (data) ؛
user.getWsoutBound (). writeTextMessage (temp) ؛
} catch (ioException e) {
// TODO AUTO CATCH BLOCK
E.PrintStackTrace () ؛
}
}
}
}
/// …………
}
لقد وجد أن الرسالة قد أرسلها العميل. وفقًا لاسم الطرف الآخر ، ابحث في قائمة العملاء المتصلين حاليًا وأرسل الرسالة إليه.
JS
وظيفة handledata (البيانات)
{
var vals = data.split (/t) ؛
var msgtype = vals [0] ؛
التبديل (msgtype)
{
/// ...
حالة MSG:
var val2s = vals [1] .Split (_) ؛
var from = val2s [0] ؛
رسالة var = val2s [2] ؛
تنبيه (من+:+رسالة) ؛
استراحة؛
تقصير:
استراحة؛
}
}
وقد وجد أنها كانت رسالة أرسلها عميل آخر ، وتم عرضها من خلال تنبيه
جافا
@تجاوز
void onclose (int state) {
users.remove (هذا) ؛
}
اكتشف العميل قد غادر ، قم بإزالة العميل من قائمة العملاء المتصلة
حيث تتحسن
1. إذا كان العميل يرسل رسالة إلى B و B غير متصل بالإنترنت ، فيمكن تخزين الرسالة في قاعدة البيانات. عندما يتم العثور على B ليكون متصلاً بالإنترنت ، سيتم استرداده من قاعدة البيانات وإرساله إلى B.
2 عندما يرسل الخادم اسمك ، يمكنه إضافة آلية مهلة. إذا لم يرد العميل على ما يطلق عليه خلال فترة زمنية معينة ، فيمكن للعميل حذف العميل من القائمة عبر الإنترنت.