어떻게 JS WebSocket 으로 간단 한 채 팅 을 실현 합 니까?

짧 은 폴 링(폴 링)
짧 은 폴 링 의 실현 방향 은 브 라 우 저 측 이 몇 초 마다 서버 측 에 HTTP 요청 을 보 내 는 것 이다.서버 는 요청 을 받 은 후에 데이터 업데이트 가 있 든 없 든 직접 응답 하 는 것 이다.서버 응답 이 완료 되면 이 TCP 연결 을 닫 습 니 다.코드 구현 도 가장 간단 합 니 다.바로 XHR 를 이용 하여 setInterval 을 통 해 정기 적 으로 백 엔 드 에 요청 을 보 내 최신 데 이 터 를 얻 는 것 입 니 다.

setInterval(function() {
  fetch(url).then((res) => {
      // success code
  })
}, 3000);
장점:실현 이 간단 하 다.
단점:데이터 가 짧 은 시간 동안 동기 화 되 지 않 고 대량의 무효 한 요청 을 초래 하여 안전성 이 떨 어 지고 자원 을 낭비 할 수 있 습 니 다.
긴 폴 링(롱 폴 링)
클 라 이언 트 가 요청 을 보 낸 후 서버 측 에서 데 이 터 를 즉시 되 돌려 주지 않 습 니 다.서버 측 에서 요청 연결 을 막 을 수 있 습 니 다.서버 측 에서 데이터 업데이트 가 있 거나 연결 시간 이 초과 되 어서 야 돌아 갑 니 다.클 라 이언 트 는 다시 새로운 연결 을 요청 하고 이렇게 반복 해서 최신 데 이 터 를 가 져 옵 니 다.대략적인 효 과 는 다음 과 같다.

클 라 이언 트 코드 는 다음 과 같 습 니 다.

function async() {
    fetch(url).then((res) => {
        async();
        // success code
    }).catch(() => {
        //   
        async();
    })
}
장점:폴 링 보다 최적화 되 어 실효 성 이 좋 습 니 다.
단점:연결 을 유지 하면 자원 이 소모 되 고 서버 가 유효한 데 이 터 를 되 돌려 주지 않 아 프로그램 이 시간 을 초과 합 니 다.
WebSocket
앞에서 언급 한 짧 은 폴 링(Polling)과 긴 폴 링(Long-Polling)은 모두 클 라 이언 트 가 먼저 Ajax 요청 을 해 야 통신 을 할 수 있 고 HTTP 프로 토 콜 을 가 야 서버 측 에서 클 라 이언 트 에 게 정 보 를 자발적으로 전송 할 수 없습니다.
스포츠 경기,채 팅 방,실시 간 위치 와 같은 장면 이 나 올 때 폴 링 은 매우 비효 율 적 이 고 자원 을 낭비 하 는 것 으로 보인다.요청 을 계속 보 내 고 서버 를 연결 해 야 하기 때문이다.웹 소켓 의 등장 으로 서버 측 이 자발적으로 클 라 이언 트 에 정 보 를 보 낼 수 있 게 하여 브 라 우 저 는 실시 간 양 방향 통신 능력 을 갖 추 게 되 었 다.
웹 소켓 을 사용 해 본 적 이 없 는 사람 은 그것 이 어떤 심오 한 기술 이 라 고 생각 할 수도 있다.그렇지 않 으 면 웹 소켓 에서 자주 사용 하 는 API 가 많 지 않 고 쉽게 파악 할 수 있 지만 어떻게 사용 하 는 지 소개 하기 전에 통신 원 리 를 살 펴 보 자.
통신 원리
클 라 이언 트 가 서버 와 웹 소켓 연결 을 하려 고 할 때 클 라 이언 트 와 서버 의 악 수 를 하 는 과정 에서 클 라 이언 트 는 먼저 서버 에 HTTP 요청 을 보 냅 니 다.Upgrade 요청 헤드 를 포함 하여 서버 클 라 이언 트 가 웹 소켓 연결 을 만 들 려 고 하 는 것 을 알 립 니 다.
클 라 이언 트 에 웹 소켓 연결 을 만 드 는 것 은 매우 간단 합 니 다.

let ws = new WebSocket('ws://localhost:9000');
HTTP 와 HTTPS 와 유사 하 며,ws 에 대응 하 는 뉴스 도 있 으 며,로 컬 뉴스 를 예 로 들 었 다.이 요청 머리 는 다음 과 같 습 니 다.

Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: Upgrade    //           
Cookie: _hjMinimizedPolls=358479; ts_uid=7852621249; CNZZDATA1259303436=1218855313-1548914234-%7C1564625892; csrfToken=DPb4RhmGQfPCZnYzUCCOOade; jsESSIONID=67376239124B4355F75F1FC87C059F8D; _hjid=3f7157b6-1aa0-4d5c-ab9a-45eab1e6941e; acw_tc=76b20ff415689655672128006e178b964c640d5a7952f7cb3c18ddf0064264
Host: localhost:9000
Origin: http://localhost:9000
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: 5fTJ1LTuh3RKjsJxydyifQ==        //      Sec-WebSocket-Accept    
Sec-WebSocket-Version: 13    //    websocket      
Upgrade: websocket    //        websocket   
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/76.0.3809.132 Safari/537.36
응답 머리 는 다음 과 같 습 니 다:

Connection: Upgrade
Sec-WebSocket-Accept: ZUip34t+bCjhkvxxwhmdEOyx9hE=
Upgrade: websocket

이 때 응답 줄(Genel)에서 상태 코드 status code 가 101 Switching Protocols 인 것 을 볼 수 있 으 며,이 연결 이 HTTP 프로 토 콜 에서 WebSocket 통신 프로 토 콜 로 전환 되 었 음 을 나타 낸다.전환 에 성공 한 후에 이 연결 은 중단 되 지 않 고 전 쌍 공 통신 을 구축 하여 후속 적 으로 메 시 지 를 보 내 고 받 으 면 이 연결 채널 로 갑 니 다.
요청 헤드 에 Sec-webSocket-Key 필드 가 있 습 니 다.해당 헤드 에 있 는 Sec-webSocket-Accept 와 세트 로 대응 합 니 다.그 역할 은 악의 적 인 연결 이나 잘못된 연결 등 기본 적 인 방 호 를 제공 하 는 것 입 니 다.Sec-webSocket-Key 는 클 라 이언 트 가 무 작위 로 생 성 한 base 64 인 코딩 입 니 다.서버 는 이 인 코딩 을 사용 하고 고정된 알고리즘 에 따라:

GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";    //          
accept = base64(sha1(key + GUID));    // key    Sec-WebSocket-Key  ,accept    Sec-WebSocket-Accept  
그 중에서 GUID 문자열 은 RFC 6455 가 공식 적 으로 정의 한 고정 문자열 로 수정 할 수 없습니다.
클 라 이언 트 가 서버 에서 응답 하 는 Sec-webSocket-Accept 를 받 으 면 자신 이 이전에 생 성 한 Sec-webSocket-Key 를 같은 알고리즘 으로 계산 하고 일치 하면 악 수 를 성공 적 으로 합 니 다.그리고 HTTP Response 상태 코드 가 101(전환 프로 토 콜)인지 판단 하고,그렇다면 연결 을 만들어 큰 성 과 를 거 두 었 다.
간단 한 잡담 을 실현 하 다.
다음은 순수한 문자 메시지 유형의 일대일 채 팅(단일 채 팅)기능 을 실현 합 니 다.쓸데없는 말 은 하지 않 고 코드 를 직접 올 리 고 주석 을 주의 깊 게 봅 니 다.
클 라 이언 트:

function connectWebsocket() {
    ws = new WebSocket('ws://localhost:9000');
    //       
    ws.onopen = () => {
        console.log('     WebSocket  ');
        ws.send(JSON.stringify(msgData));    // send           
    };

    //        (    )
    ws.onmessage = (msg) => {
        let message = JSON.parse(msg.data);
        console.log('     :', message)
        elUl.innerhtml += `<li>  :${message.content}</li>`;
    };

    //       
    ws.onerror = () => {
        console.log('    ,    ...');
        connectWebsocket();
    };

    //       
    ws.onclose = () => {
        console.log('    ');
    };
};
connectWebsocket();
위 에서 웹 소켓 인 스 턴 스 를 볼 수 있 는 API 는 이해 하기 쉽 고 간단 하 며 send()방법 으로 메 시 지 를 보 낼 수 있 습 니 다.onmessage 이 벤트 는 메 시 지 를 받 은 다음 메 시 지 를 처리 하여 페이지 에 표시 합 니 다.onerror 이벤트(감청 연결 실패)가 실 행 될 때 연결 이 끊 기지 않도록 다시 연결 하 는 것 이 좋 습 니 다.
서버 노드:(여기 ws 라 이브 러 리 사용)

const path = require('path');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const WebSocket = require('ws');

const wss = new WebSocket.Server({ server: server });

wss.on('connection', (ws) => { 

  //           
  ws.on('message', (message) => {
    console.log(wss.clients.size);
    let msgData = JSON.parse(message);   
    if (msgData.type === 'open') {
      //          
      ws.sessionId = `${msgData.fromUserId}-${msgData.toUserId}`;
    } else {
      let sessionId = `${msgData.toUserId}-${msgData.fromUserId}`;
      wss.clients.forEach(client => {
        if (client.sessionId === sessionId) {
          client.send(message);     //              
        }
      })  
    }
  })

  //     
  ws.on('close', () => {
    console.log('    ');  
  });
});
마찬가지 로 서버 에 도 해당 하 는 발송 과 수신 방법 이 있다.전체 예제 코드 여기 있 습 니 다.
이렇게 하면 브 라 우 저 와 서버 에서 즐겁게 메 시 지 를 보 낼 수 있 습 니 다.효 과 는 다음 과 같 습 니 다.

그 중에서 녹색 화살 표 는 보 낸 소식 을 나타 내 고 빨간색 화살 표 는 받 은 소식 을 나타 낸다.
심장 박동 이 잘 풀리다.
실제 웹 소켓 을 사용 할 때 장시간 통 하지 않 으 면 연결 이 불안정 할 수 있 습 니 다.이러한 알 수 없 는 상황 으로 인 한 연결 중단 은 클 라 이언 트 와 서버 이전의 통신 에 영향 을 줄 수 있 습 니 다.
이러한 상황 을 방지 하기 위해 심장 박동 을 유지 하 는 방법 이 있 습 니 다.클 라 이언 트 는 심장 박동 처럼 정 해진 시간 마다 ping 을 보 내 서 서버 에 제 가 살아 있다 는 것 을 알려 주 고 서버 도 pong 으로 돌아 가 클 라 이언 트 에 게 서버 가 살아 있다 는 것 을 알려 줍 니 다.ping/pong 은 사실 업무 와 무관 한 가짜 소식 으로 심장 박동 가방 이 라 고도 부른다.
연결 에 성공 한 후 고정 시간 마다 심장 박동 가방 을 보 낼 수 있 습 니 다.예 를 들 어 60s:

setInterval(() => {
    ws.send('         ');
}, 60000)
총결산

위의 소 개 를 통 해 여러분 들 은 웹 소켓 에 대해 어느 정도 알 게 되 었 을 것 입 니 다.사실은 신비 하지 않 습 니 다.여기 서 글 의 내용 을 간단하게 정리 하 겠 습 니 다.웹 소켓 인 스 턴 스 를 만 들 때 HTTP 요청 을 보 냅 니 다.메시지 에 특수 한 필드 Upgrade 를 요청 한 다음 에 이 연결 은 HTTP 프로 토 콜 에서 웹 소켓 프로 토 콜 로 전 환 됩 니 다.그러면 클 라 이언 트 와 서버 는 양 방향 통신 을 구축 하고 웹 소켓 의 send 방법 과 onmessage 사건 을 통 해 이 통신 연결 을 통 해 정 보 를 교환 할 수 있 습 니 다.
이상 은 JS WebSocket 으로 간단 한 채 팅 을 하 는 방법 에 대한 상세 한 내용 입 니 다.WebSocket 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 세 요!

좋은 웹페이지 즐겨찾기