ক্লায়েন্টের পুনঃসংযোগ যখন সার্ভারটি ওয়েবসকেটে পুনরায় চালু হয়


94

আমি পিএইচপি 5 এবং ক্লায়েন্ট হিসাবে ক্রোম ব্রাউজার ব্যবহার করে ওয়েব সকেট ব্যবহার করছি। আমি সাইটটি থেকে কোডটি নিয়েছি http://code.google.com/p/phpwebsket/

আমি সার্ভারটি চালনা করি এবং ক্লায়েন্টটিও সংযুক্ত। আমিও চ্যাট করতে পারি। এখন যখন আমি সার্ভারটি পুনরায় চালু করব (এটি মেরে এবং আবার শুরু করে) তখন ক্লায়েন্টটি সংযোগ বিচ্ছিন্ন হয়ে যায় তবে আমি বার্তাটি প্রেরণ করার পরে স্বয়ংক্রিয়ভাবে সার্ভারের সাথে পুনরায় সংযোগ স্থাপন করে না।

কীভাবে এটি অর্জন করবেন? আমি যখন ডিস-সংযুক্ত তথ্য পাই, তখন কি আমি এটি পরীক্ষা করে পৃষ্ঠাটি রিফ্রেশ করতে পুনরায় সংযোগ করতে জাভাস্ক্রিপ্টে প্রেরণ করব?

উত্তর:


143

সার্ভারটি পুনরায় বুট করার পরে, ওয়েব সকেট সংযোগটি বন্ধ হয়ে যায়, তাই জাভাস্ক্রিপ্ট oncloseইভেন্টটি ট্রিগার করে। এখানে একটি উদাহরণ যা প্রতি পাঁচ সেকেন্ডে পুনরায় সংযোগ করার চেষ্টা করে।

function start(websocketServerLocation){
    ws = new WebSocket(websocketServerLocation);
    ws.onmessage = function(evt) { alert('message received'); };
    ws.onclose = function(){
        // Try to reconnect in 5 seconds
        setTimeout(function(){start(websocketServerLocation)}, 5000);
    };
}

4
আমি আশা করেছিলাম যে কোনও নতুন অবজেক্ট তৈরি না করে এবং ইভেন্টের ক্রিয়াগুলি সংজ্ঞায়িত না করে আরও মার্জিত উপায় আছে ...
ciembor

4
5 মিনিটের পরে, ব্রাউজারটি হিমশীতল। আমি শুধু এক নই?
মার্ক

16
আপনার "ws = নাল;" যোগ করা উচিত; গুড ডাব্লুএস বস্তু এবং ইভেন্টহ্যান্ডলিগগুলি এড়াতে সেটটাইমআউট () এর আগে
সর্বোচ্চ

8
আমি ভুল হলে আমাকে সংশোধন করুন, তবে এই কোডটি বিপদজনক কারণ নির্দিষ্ট পরিমাণে সংযোগ বিচ্ছিন্নভাবে স্ট্যাকের ওভারফ্লো হতে পারে। কারণ আপনি startকখনই ফিরে না আসায় পুনরাবৃত্তভাবে কল করেন ।
ফোরইভিন

11
@ ফোরিভিন এখানে কোন স্ট্যাকওভারফ্লো ইস্যু নেই। যে কোনও মুহুর্তে জাভাস্ক্রিপ্টে কেবলমাত্র 1 টি একক থ্রেড রয়েছে যা আমাদের কোডকে নির্ধারিত মুহুর্তে কার্যকর করে, সেটটাইমআউট () ভবিষ্যতে সম্পাদিত হওয়া ফাংশনটির শিডিয়ুল করে যখন সেই একক থ্রেডটি আবার মুক্ত হয়। এখানে সেটটাইমআউট () বলা হওয়ার পরে, থ্রেডটি ফাংশন থেকে ফিরে আসে (স্ট্যাকটি সাফ করে), তারপরে পরবর্তী ইভেন্টটি কাতারে প্রক্রিয়া করতে যায়। এটি শেষ পর্যন্ত আমাদের বেনামে ফাংশনটি পেয়ে যাবে যা কল কল শুরু করে এবং এটিকে স্ট্যাকের শীর্ষ ফ্রেম হিসাবে ডাকা হবে।
দুর্গন্ধযুক্ত

40

অ্যান্ড্রু প্রদত্ত সমাধানটি পুরোপুরি কার্যকর হচ্ছে না কারণ, হারিয়ে যাওয়া সংযোগের ক্ষেত্রে সার্ভারটি বেশ কয়েকটি ঘনিষ্ঠ ইভেন্ট পাঠাতে পারে।

সেক্ষেত্রে আপনি বেশ কয়েকটি সেটটাইমআউট সেট করবেন। অ্যান্ড্রু প্রদত্ত সমাধানটি কেবল তখনই কাজ করতে পারে যদি সার্ভারটি পাঁচ সেকেন্ডের আগে প্রস্তুত থাকে।

তারপরে, অ্যান্ড্রু সমাধানের উপর ভিত্তি করে, পুনরায় কাজ শুরু করে, আমি উইন্ডো অবজেক্টে আইডি সংযুক্ত করে সেট ইনটারভাল ব্যবহার করেছি (এইভাবে এটি "সর্বত্র উপলব্ধ"):

var timerID=0;

var socket;

/* Initiate what has to be done */

socket.onopen=function(event){
 /* As what was before */
 if(window.timerID){ /* a setInterval has been fired */
   window.clearInterval(window.timerID);
   window.timerID=0;
 }
 /* ... */
}

socket.onclose=function(event){
  /* ... */
 if(!window.timerID){ /* Avoid firing a new setInterval, after one has been done */
  window.timerID=setInterval(function(){start(websocketServerLocation)}, 5000);
 }
 /* That way, setInterval will be fired only once after losing connection */
 /* ... */
}

আপনি setTimeoutযদি তাদের জন্য "গ্লোবাল টাইমার আইডি" ধারণাটি প্রয়োগ করেন তবে আপনি এখনও ব্যবহার করতে পারবেন ;)
রোজা

4
"অ্যান্ড্রু প্রদত্ত সমাধানটি কেবল তখনই কাজ করতে পারে যদি সার্ভারটি পাঁচ সেকেন্ডের আগে প্রস্তুত থাকে" "- বিবৃতিটি সত্য নয়। যদি সার্ভারটি পাঁচ সেকেন্ড পরেও অনুপলব্ধ থাকে তবে আপনার ক্লায়েন্ট ওয়েবস্কট সংযোগটি খুলতে ব্যর্থ হবে এবং oncloseইভেন্টটি আবার বরখাস্ত করা হবে।
সৌরভ ঘোষ

36

ওয়েলসকেট পুনরায় সংযুক্ত হচ্ছে

গিটহাব একটি ছোট জাভাস্ক্রিপ্ট লাইব্রেরি হোস্ট করে যা ওয়েবস্কট এপিআইটিকে একটি ওয়েবস্কট সংযোগ সরবরাহ করতে সজ্জিত করে যা সংযোগটি বাদ দিলে স্বয়ংক্রিয়ভাবে পুনরায় সংযোগ স্থাপন করবে।

জিজিপ সংকোচনের সাথে সংক্ষিপ্ত গ্রন্থাগারটি 600 বাইটের চেয়ে কম।

অফিসিয়াল সংগ্রহস্থলটি এখানে উপলভ্য:

https://github.com/joewalnes/reconnecting-websket

সার্ভার বন্যা

সার্ভারের সাথে সংখ্যক ক্লায়েন্ট সংযুক্ত থাকলে এটি পুনরায় চালু হয়। এক্সপেনশনাল ব্যাকঅফ অ্যালগরিদম ব্যবহার করে ক্লায়েন্টদের পুনরায় সংযোগের সময়গুলি পরিচালনা করা সার্থক হতে পারে।

অ্যালগরিদম এইভাবে কাজ করে:

  1. কে প্রয়াসের জন্য, 0 এবং 2 ^ কে - 1 এর মধ্যে সময়ের এলোমেলো ব্যবধান তৈরি করুন,
  2. আপনি যদি পুনরায় সংযোগ করতে সক্ষম হন তবে k কে 1 এ রিসেট করুন,
  3. যদি পুনরায় সংযোগ ব্যর্থ হয়, কে 1 দিয়ে বৃদ্ধি পায় এবং প্রক্রিয়াটি প্রথম ধাপে পুনরায় শুরু হয়,
  4. সর্বোচ্চ ব্যবধানটি কেটে ফেলতে, যখন একটি নির্দিষ্ট সংখ্যক প্রচেষ্টা পৌঁছে যায়, প্রতিটি চেষ্টা করার পরে কে ক্রমবর্ধমান বন্ধ করে দেয়।

রেফারেন্স:

http

পুনরায় সংযোগকারী ওয়েবসকেট এই অ্যালগরিদমটি ব্যবহার করে পুনরায় সংযোগগুলি পরিচালনা করে না।


দুর্দান্ত উত্তর, বিশেষত কারণ এটি একবারে একটি উচ্চ সার্ভার লোড হওয়ার ঝুঁকির কথা উল্লেখ করে যখন একবার সার্ভার ওয়েব সকেট সংযোগগুলি বন্ধ করে দেয় এবং সমস্ত ক্লায়েন্ট (যা কয়েকশো বা কয়েক হাজার হতে পারে) একই সাথে পুনরায় সংযোগ করার চেষ্টা করে। ঘৃণ্য ব্যাকঅফের পরিবর্তে, আপনি 0 থেকে 10 সেকেন্ডের মতো বিলম্বটি এলোমেলো করতেও পারেন। এটি সার্ভারেও লোডটি ছড়িয়ে দেবে।
জোহেম শুলেনক্লাপ্পার

29

খাঁটি ভ্যানিলা জাভাস্ক্রিপ্টের জন্য আমি এই প্যাটেনটি কিছু সময়ের জন্য ব্যবহার করছি এবং এটি অন্যান্য উত্তরের চেয়ে আরও কয়েকটি ক্ষেত্রে সমর্থন করে।

document.addEventListener("DOMContentLoaded", function() {

  'use strict';

  var ws = null;

  function start(){

    ws = new WebSocket("ws://localhost/");
    ws.onopen = function(){
      console.log('connected!');
    };
    ws.onmessage = function(e){
      console.log(e.data);
    };
    ws.onclose = function(){
      console.log('closed!');
      //reconnect now
      check();
    };

  }

  function check(){
    if(!ws || ws.readyState == 3) start();
  }

  start();

  setInterval(check, 5000);


});

সার্ভারটি সংযোগ বন্ধ করার সাথে সাথেই এটি আবার চেষ্টা করবে এবং এটি প্রতি 5 সেকেন্ডের মধ্যেও শেষ হয়েছে তা নিশ্চিত করার জন্য এটি সংযোগটি পরীক্ষা করবে।

সুতরাং যখন সার্ভারটি চালু না থাকে বা অনক্লোজ ইভেন্টের সময় সংযোগটি এটি অনলাইনে ফিরে আসার পরেও ফিরে আসবে।

দ্রষ্টব্য: এই স্ক্রিপ্টটি ব্যবহার করা আপনাকে কোনও সংযোগ খোলার চেষ্টাটি কখনও থামিয়ে দেবে না ... তবে আমি মনে করি এটি আপনি কী চান?


7
আমি কেবল পরিবর্তন করব: ফাংশন চেক () {যদি (! ডাব্লুএস || ডাব্লু .এসডিআর স্টেট === ওয়েবসকেট.সিএলওএসডি) শুরু (); }
ডায়ারিসিস

4
এই পদ্ধতির সাথে সাথে এখানে বর্ণিত রাখার জন্য জীবিত কৌশলটি আমার পক্ষে ভাল কাজ করে বলে মনে হচ্ছে।
পিটার

@ পিটার, নিশ্চিত নন যে ডাব্লুএসের রাজ্যটি খোলা আছে কিনা আপনার পিং দরকার (বা হওয়া উচিত), যদি আমি সঠিক হয়ে থাকি তবে এটি ইতিমধ্যে ওয়েবসকেট প্রোটোকলে রয়েছে। এই ওভারকিলটির সবেমাত্র আপনার সার্ভারে লোড ছিল ...
comte

@ কম্ট কিছু ডাব্লু সার্ভার ক্লায়েন্টের কাছ থেকে কোনও বার্তা প্রেরণ না হওয়ার 'নিষ্কলুষ সময়ের' পরে আপনাকে সংযোগ বিচ্ছিন্ন করে এবং তাই সংযোগটি উন্মুক্ত রাখতে, পিংটি একটি খারাপ প্রয়োজনীয়তা।
রোজা

2

নীচে আমার প্রকল্পে আমি ব্যবহার করা কোডগুলি যা 100% কাজ করে।

  1. সমস্ত ফাংশনের ভিতরে ওয়েবসকেট কোডটি রাখুন।
  2. অনক্লোজ কলব্যাকের ভিতরে আবার কল করুন কল করুন।
  3. শেষ পর্যন্ত ডকুমেন্টের জন্য ফাংশনটির ভিতরে ফাংশনটি কল করুন।

var name = sessionStorage.getItem ('নাম');

wsUri =  "ws://localhost:8080";   
var websocket;
$(function() {  
    init();  
    $("#chat_text_box").on("keypress", function(e) {         
        if (e.keyCode == 13) {   //For Enter Button    
            e.preventDefault();
            var mymessage = $('#chat_text_box').val();               
            if(mymessage){
                var msg = {  type: 'chat_text',  data : {  name:name,  msg:mymessage }  };                
                console.log(msg);
                websocket.send(JSON.stringify(msg));
                $('#chat_text_box').val('');
            }               
            return false;                       
        }        
    });      
});     
function init() { 
    websocket = new WebSocket(wsUri);      
    websocket.onopen = function(ev) { /*connection is open */    } 
    websocket.onmessage = function(ev) {        
        var data = JSON.parse(ev.data); //PHP sends Json data        
        var type = data.type;//alert(JSON.stringify(data));
        switch(type) {
            case "chat_text":
                var text = "<div><span class='user'>"+data.data.sender_name+" : </span><span class='msg'>"+data.data.msg+"</span></div>";
                $('#chat-messages').append(text);
                break;            
            default:
                break;

        }        

    };     
    websocket.onerror   = function(ev){}; 
    websocket.onclose = function(ev) {   init();   };  
}

2

মন্তব্য করতে পারবেন না, তবে নিম্নলিখিতগুলি:

var socket;

const socketMessageListener = (event) => {
  console.log(event.data);
};

const socketOpenListener = (event) => {
  console.log('Connected');
  socket.send('hello');
};

const socketCloseListener = (event) => {
  if (socket) {
    console.error('Disconnected.');
  }
  socket = new WebSocket('ws://localhost:8080');
  socket.addEventListener('open', socketOpenListener);
  socket.addEventListener('message', socketMessageListener);
  socket.addEventListener('close', socketCloseListener);
};

socketCloseListener();

// for testing
setTimeout(()=>{
  socket.close();
},5000);

প্লাস https://www.npmjs.com/package/back ইতিমধ্যে যথেষ্ট ভাল :)


1

function wsConnection(url){
    var ws = new WebSocket(url);
    var s = (l)=>console.log(l);
	ws.onopen = m=>s(" CONNECTED")
    ws.onmessage = m=>s(" RECEIVED: "+JSON.parse(m.data))
    ws.onerror = e=>s(" ERROR")
    ws.onclose = e=>{
        s(" CONNECTION CLOSED");
        setTimeout((function() {
            var ws2 = new WebSocket(ws.url);
			ws2.onopen=ws.onopen;
            ws2.onmessage = ws.onmessage;
            ws2.onclose = ws.onclose;
            ws2.onerror = ws.onerror;
            ws = ws2
        }
        ).bind(this), 5000)
    }
    var f = m=>ws.send(JSON.stringify(m)) || "Sent: "+m;
    f.ping = ()=>ws.send(JSON.stringify("ping"));
    f.close = ()=>ws.close();
    return f
}

c=new wsConnection('wss://echo.websocket.org');
setTimeout(()=>c("Hello world...orld...orld..orld...d"),5000);
setTimeout(()=>c.close(),10000);
setTimeout(()=>c("I am still alive!"),20000);
<pre>
This code will create a websocket which will 
reconnect automatically after 5 seconds from disconnection.

An automatic disconnection is simulated after 10 seconds.


0

অবশেষে, আমি নীচের মতোই ভ্যু + টিএসে ডাব্লুএসকে অটো পুনঃসংযোগ করি:

private async mounted() {
    // Connect to WebSocket
    const sn = "sb1234567890";
    const host =
        window.location.protocol == "https:"
            ? "wss://www.xxx.net"
            : process.env.DEV_TYPE === "fullstack"
            ? "ws://10.0.0.14:8528"
            : "ws://www.xxx.net:8528";
    const wsUri = host + "/feed-home/" + sn;
    await this.startWs(wsUri, sn);
    // !!!Deprecated: failed to reconnect
    // let ws = new WebSocket();
    // console.log(ws);
    // ws.onopen = async function(event) {
    //     console.log(event, "openEvent");
    //     clearInterval(that.timer);
    // };
    // ws.onclose = async function(event) {
    //     console.log(event, "close");
    //     that.timer = setInterval(() => {
    //         console.log("Heart Beat");
    //         ws.send("HeartBeat");
    //         // ws = new WebSocket("ws://10.0.0.14:8528/feed-home/" + sn);
    //         console.log(ws);
    //     }, 60000);
    // };
    // ws.onmessage = async function(event) {
    //     console.log(event, "ws");
    //     alert("get it!");
    //     await alert("please update!");
    //     await that.getHome(sn);
    // };
}
private wsReconnected: boolean = false; // check whether WebSocket is reconnected
private async startWs(uri: string, sn: string) {
    let that = this;
    let ws = new WebSocket(uri);
    ws.onopen = async () => {
        if (that.wsReconnected) {
            await that.getHome(sn); // Refresh api data after reconnected
        }
        ws.send("Current client version: " + window.version);
    };
    ws.onmessage = async evt => {
        await that.getHome(sn);
        that.$message({
            type: "success",
            message: evt.data,
            showClose: true,
            center: true,
            duration: 20 * 1000
        });
    };
    ws.onclose = async () => {
        that.wsReconnected = true;
        await that.startWs(uri, sn);
        const sleep = (seconds: number) => {
            return new Promise(resolve =>
                setTimeout(resolve, seconds * 1000)
            );
        };
        await sleep(10); // Try to reconnect in 10 seconds
        // !!!Deprecated: Use timer will cause multiply ws connections
        // if (!that.wsTimer) {
        //     // Try to reconnect in 10 seconds
        //     that.wsTimer = setInterval(async () => {
        //         console.log("reconnecting websocket...");
        //         await that.startWs(uri, sn);
        //     }, 10 * 1000);
        // }
    };
}

0

ওয়েবসকেটের ক্লায়েন্ট সাইড ক্লোজ ইভেন্টের একটি ওয়েস ক্লিন সম্পত্তি রয়েছে, যা আমার জন্য দরকারী। মনে হয় এটি ক্লায়েন্ট কম্পিউটার স্লিপ মোডে চলে যায় ইত্যাদি ক্ষেত্রে বা সার্ভারের অপ্রত্যাশিতভাবে বন্ধ হয়ে যাওয়া ইত্যাদি ক্ষেত্রে এটি সত্য হিসাবে সেট করা মনে হয় যদি আপনি নিজেই সকেটটি বন্ধ করে দেন তবে এটি মিথ্যাতে সেট করা আছে, সেক্ষেত্রে আপনি খুলতে চান না আবার সকেট স্বয়ংক্রিয়ভাবে। একটি কৌণিক 7 প্রকল্পের কোডের নীচে। আমার একটি পরিষেবাতে এই কোড রয়েছে, সুতরাং এটি কোনও উপাদান থেকে ব্যবহারযোগ্য।

    notifySocketClose(event) { 

        if (!event.wasClean) { 
            setTimeout(() => {
                this.setupSocket()
            }, 1000);       
        }
    }

    setupSocket() { // my function to handle opening of socket, event binding etc.
    .....
    .....

            this.websocketConnection = this.websocketConnection ? this.websocketConnection : new WebSocket(socketUrl);
            this.websocketConnection.onclose = this.notifySocketClose.bind(this);   
        } 
    }
    .....
    .....

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.