두 프로그램 간 메세지를 교환하기 위한 통신방법 중 하나
클라이언트가 서버에 http 요청을 보내면 해당 서버는 클라이언트에게 데이터를 전달해준다.
통상적으로 http 통신은 클라이언트가 요청을 보내야만 서버가 응답을 해주는 방식이다. 서버가 먼저 요청을 보내는 경우는 절대 없다. 이런 통신 방식을 단방향 통신이라고 한다.
근데 만약에 실시간으로 업데이트 된 정보를 보여줘야한다고 했을 때,
실시간으로 http요청을 계속 날리는 방법도 있겠지만(polling, 폴링) 그거보다 더 효율적인 방법은 서버가 알아서 보내주는 것!
그 해결책 중 하나로 웹 소켓이 있다.
TCP통신 기반으로 클라이언트와 서버가 양방향 통신이 가능해진다.
```
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade // or Upgrade: websocket => 웹소켓 요청임을 표시
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== // 핸드쉐이크 응답을 검증할 키값
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
```
HTTP/1.1 101 Switching Protocols // 정상적인 응답의 상태코드: 101
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
웹소켓 통신은 '프레임' 단위로 이뤄진다. 프레임은 데이터 조각을 말한다. 프레임은 서버와 클라이언트 양측에서 보낼 수 있다. 프레임 내 담긴 데이터 종류에 따라 프레임을 다음과 같이 분류할 수 있다.
브라우저 환경에서 개발자는 텍스트나 이진 데이터 프레임만 다루게 됨
WHY?
WebSocket의 .send()
메서드는 텍스트나 이진 데이터만 보낼 수 있기 때문
END
Opcode
Length
연결 주체(브라우저나 서버) 중 한 쪽에서 커넥션 닫기(close)를 원하는 경우 보통 숫자로된 코드와 문자로 된 사유가 담긴 connection close frame
을 전송함
// close를 요청한 주체
socket.close(1000, "Work complete"); // socket.close([code], [reason])
// close 요청을 받은 주체
socket.onclose = event => {
//event.code === 1000
//event.reason === "작업 완료"
}
1000
: 기본값. 정상 종료를 의미함1006
: 1000
같은 코드를 수동으로 설정할 수 없을 때 사용. 커넥션이 유실(no close frame)되었음을 의미함socket.send(message)
를 사용해 message 전송let socket = new WebSocket("wss://javascript.info/article/websocket/chat/ws"); // 클라이언트가 서버에 웹소켓으로 통신하고 싶다고 요청을 보냄
// 폼에 있는 메시지를 전송
document.forms.publish.onsubmit = function() {
let outgoingMessage = this.message.value;
socket.send(outgoingMessage); // 웹소켓 연결 후 클라이언트가 서버에 웹소켓으로 메세지 보내기
return false;
};
// 메시지를 수신하고, 수신한 메시지를 div#messages에 보여줌
socket.onmessage = function(event) {
let message = event.data;
let messageElem = document.createElement('div');
messageElem.textContent = message;
document.getElementById('messages').prepend(messageElem);
}
ws
vs wss
clients.add(socket)
에 추가해주고 message
의 이벤트리스너에 set 해준다clients.delete(socket)
// 클라이언트의 웹소켓통신 요청을 허락해 줌. http통신을 웹소켓으로 업그레이드 해줌
const ws = new require('ws');
const wss = new ws.Server({noServer: true});
const clients = new Set();
http.createServer((req, res) => {
// here we only handle websocket connections
// in real project we'd have some other code here to handle non-websocket requests
wss.handleUpgrade(req, req.socket, Buffer.alloc(0), onSocketConnect);
});
function onSocketConnect(ws) {
clients.add(ws);
ws.on('message', function(message) { //클라이언트가 보낸 웹소켓 메세지를 서버가 수신
message = message.slice(0, 50); // max message length will be 50
for(let client of clients) {
client.send(message); // send message back => 클라이언트에게 다시 메세지 보내기
}
});
ws.on('close', function() {
clients.delete(ws);
});
}
ws 대신 socket.io 라이브러리를 쓰면 좋은 이유
참고자료