bestsource

웹소켓:죽은 후 자동으로 다시 연결하는 방법

bestsource 2023. 10. 31. 22:26
반응형

웹소켓:죽은 후 자동으로 다시 연결하는 방법

var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function () {
  ws.send(JSON.stringify({
      .... some message the I must send when I connect ....
  }));

};

ws.onmessage = function (e) {
  console.log('Got a message')
  console.log(e.data);
};

ws.onclose = function(e) {  
  console.log('socket closed try again'); 

}

ws.onerror = function(err) {
  console.error(err)
};

처음 소켓에 접속할 때는 먼저 서버에 메시지를 보내 본인 인증과 채널 가입을 해야 합니다.

내가 가진 문제는 소켓 서버가 때때로 신뢰할 수 없다는 것과 그것이 유발한다는 것입니다.onerror그리고.onclose의 사건들'ws'물건.

질문:.소켓이 닫히거나 오류가 발생할 때마다 10초 동안 기다렸다가 소켓 서버에 다시 연결할 수 있는 좋은 설계 패턴은 무엇입니까(그리고 처음 메시지를 서버에 다시 전송).

이것이 제가 얻은 결과입니다.그것은 제 목적에 맞게 작동합니다.

function connect() {
  var ws = new WebSocket('ws://localhost:8080');
  ws.onopen = function() {
    // subscribe to some channels
    ws.send(JSON.stringify({
        //.... some message the I must send when I connect ....
    }));
  };

  ws.onmessage = function(e) {
    console.log('Message:', e.data);
  };

  ws.onclose = function(e) {
    console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
    setTimeout(function() {
      connect();
    }, 1000);
  };

  ws.onerror = function(err) {
    console.error('Socket encountered error: ', err.message, 'Closing socket');
    ws.close();
  };
}

connect();

이것은 나에게 효과가 있었습니다.setInterval, 클라이언트 연결이 끊어질 수 있기 때문입니다.

ngOnInit(): void {
    if (window.location.protocol.includes('https')) {
        this.protocol = 'wss';
    }

    this.listenChanges();
}


listenChanges(): void {
    this.socket = new WebSocket(`${this.protocol}://${window.location.host}/v1.0/your/url`);

    this.socket.onmessage = (event): void => {
        // your subscription stuff
        this.store.dispatch(someAction);
    };

    this.socket.onerror = (): void => {
        this.socket.close();
    };


    this.socket.onopen = (): void => {
        clearInterval(this.timerId);

        this.socket.onclose = (): void => {
            this.timerId = setInterval(() => {
                this.listenChanges();
            }, 10000);
        };
    };
}

잊지말고 전화해요.clearInterval소켓이 열렸을 때.

이는 명확하게 반응형 질문은 아니지만, 다음은 반응형 답변입니다.

TLDR: 사용할 수 있습니다.setInterval웹소켓 연결 상태를 주기적으로 확인하고 연결이 종료된 경우 재연결을 시도합니다.https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState

class TestComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};

    this.connect = this.connect.bind(this);
  }

  componentDidMount() {
    this.interval = setInterval(this.connect, 1000);
  }

  componentWillUnmount() {
    if (this.ws) this.ws.close();
    if (this.interval) clearInterval(this.interval);
  }

  connect() {
    // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
    if (this.ws === undefined || (this.ws && this.ws.readyState === 3)) {
      this.ws = new WebSocket(`ws://localhost:8080`);

      this.ws.onmessage = (e) => {
        console.log(JSON.parse(e.data));
      };
    }
  }

  render() {
    return <div>Hey!</div>;
  }
}

저는 이 패키지 https://github.com/pladaria/reconnecting-websocket 가 웹소켓 연결에 대한 재연결 문제를 해결할 수 있다는 것을 알았습니다.그리고 설정 가능한 옵션 목록을 가지고 있는데, 그 중 하나는reconnectionDelayGrowFactor이것은 재접속 지연이 얼마나 빨리 증가하는지를 결정합니다.

소켓이 닫히거나 서버에 오류가 발생한 경우 비동기식 await를 사용하여 클라이언트가 5초마다 자동으로 연결을 시도합니다. 내 답변을 보십시오.

업데이트된 답변:

결국, (자바를 사용하지 않는 경우) 독자적인 "ping/pong" 전략을 구현하는 것이 좋다는 것을 알았습니다.(java를 사용하는 경우 ping/pong "action type"을 확인하십시오. 기억이 잘 나지 않습니다...)

  1. 클라이언트가 5초마다 "ping"을 서버로 전송했습니다.
  2. 서버가 "ping"을 받으면 클라이언트에 "pong"를 반향해야 합니다.
  3. 클라이언트가 5초 안에 "pong"를 수신하지 못하면 서버를 다시 연결해야 합니다.

제삼자의 입에 의지하지 마세요.

경고: 다음 도구를 사용하지 마십시오. (이유: 신뢰할 수 없고 안정적이지 않으며 매우 제한적으로 작동합니다.)

  1. 네트워크를 사용할 수 있는지 확인합니다. https://github.com/hubspot/offline
  2. 다시 연결하려면: https://github.com/joewalnes/reconnecting-websocket

저는 지난 몇 주 동안 이 문제로 어려움을 겪었고, 누군가에게 도움이 될 경우를 대비해 슈퍼소켓이라는 패키지를 만들기로 결정했습니다!이것은 네이티브 웹소켓을 대체하는 역할을 해야 합니다.제가 찾은 기존 패키지는 유지보수되지 않은 것 같습니다.

SuperSocket은 기존 WebSocket 구현의 맨 위에 있으며, 다른 기능들 중에서도 성공적으로 구현될 때까지 다시 연결해야 합니다.물론 무한 루프 및 불필요한 CPU 로드를 피하기 위해 최대 재시도를 설정할 수 있습니다. :)

//native implementation
var ws = new WebSocket('ws://localhost:8080');

//drop in replacement, embedding reconnect strategies
var ws = new SuperSocket('ws://localhost:8080');

웹소켓 재연결은 자동으로 재연결되는 API 호환 장식된 웹소켓 클래스를 제공하여 이 문제를 해결하는 작은 라이브러리입니다.

스크립트를 페이지에 추가합니다(예: a를 통해).<script>tag) 및 위 링크된 README에 의해 설명된 바와 같이:

API 호환이 가능하므로 다음을 수행할 수 있습니다.

var ws = new WebSocket('ws://....');

다음으로 대체할 수 있습니다.

var ws = new ReconnectingWebSocket('ws://....');

시도해 보기:

const observable = Observable.create(
  (obs: Observer<MessageEvent>) => {
    this.ws.onmessage = obs.next.bind(obs);
    this.ws.onerror = obs.error.bind(obs);
    // this.ws.onclose = obs.complete.bind(obs);
    this.ws.onclose = function () {
      window.location.reload()
    }
    return this.ws.close.bind(this.ws);
  });

const observer = {
  next: (data: Object) => {
    if (this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(data));
    }
  }
};

구성요소

getDatas() {
let url = environment.apiwebsocket
this.webSocketService.connect(url)
  .subscribe(evt => {
    let jsonObj = JSON.parse(evt.data)
  });}

전에 이걸 프로젝트 어딘가에 뒀었어요

let rc = new WebSocket(
    'ws://'
    + window.location.host
    + `/ws/chat/${window.seen.pk}/`
)

이제 다음으로 전환했습니다.

// ws create the websocket and returns it
function autoReconnect(ws_create){
    let ws = ws_create();
    function startReconnecting(){
        let interval = setInterval(()=>{
            console.log('trying')
            ws = ws_create();
            ws.onopen = () => {
                console.log('stop');
                ws.onclose = startReconnecting;
                clearInterval(interval);
            }
        }, 3000);
    }
    ws.onclose = startReconnecting;
}

let rc;
autoReconnect(()=>{
    rc = new WebSocket(
        'ws://'
        + window.location.host
        + `/ws/chat/${window.seen.pk}/`
    )
    return rc;
});

실행 및 로컬 호스트 중지를 통해 테스트합니다. 잘 작동합니다. (btw 이 질문은 오랫동안 게시되었지만 짧고 우아한 해결책이 없습니다.)

이 방법의 장점은 화살표 함수를 전달하여 외부 범위에 변수를 할당할 수 있다는 것입니다.

여기 제 프로젝트에서 사용하는 간단한 버전이 있습니다.여기에는 재연결을 위한 증분 대기 타이머가 포함되어 있습니다.

//wsURL - the string URL of the websocket
//waitTimer - the incrementing clock to use if no connection made
//waitSeed - used to reset the waitTimer back to default on a successful connection
//multiplier - how quickly you want the timer to grow on each unsuccessful connection attempt

const openSocket = (wsURL, waitTimer, waitSeed, multiplier) =>{
  let ws = new WebSocket(wsURL);
  console.log(`trying to connect to: ${ws.url}`);

  ws.onopen = () => {
      console.log(`connection open to: ${ws.url}`);
      waitTimer = waitSeed; //reset the waitTimer if the connection is made
      
      ws.onclose = () => {
        console.log(`connection closed to: ${ws.url}`);
        openSocket(ws.url, waitTimer, waitSeed, multiplier);
      };
      
      ws.onmessage = (message) => {
        //do something with messge...
      };
  };
  
  ws.onerror = () => {
    //increaese the wait timer if not connected, but stop at a max of 2n-1 the check time
    if(waitTimer < 60000) waitTimer = waitTimer * multiplier; 
    console.log(`error opening connection ${ws.url}, next attemp in : ${waitTimer/1000} seconds`);
    setTimeout(()=>{openSocket(ws.url, waitTimer, waitSeed, multiplier)}, waitTimer);
  }
}

openSocket(`ws://localhost:3000`, 1000, 1000, 2)

언급URL : https://stackoverflow.com/questions/22431751/websocket-how-to-automatically-reconnect-after-it-dies

반응형