브라우저와 서버간의 실시간 event-based 양방향 커뮤니케이션
이 문서에서는 client만 다룹니다.
Client
는 WebSocket
프로토콜 연결이 가능한 경우 연결하고, 아니면 HTTP long polling
으로 폴링한다.
// WebSocket API
const socket = new WebSocket("ws://localhost:3000");
socket.onopen = () => {
socket.send("Hello!");
};
socket.onmessage = (data) => {
console.log(data);
};
// Socket.IO
const socket = io("ws://localhost:3000");
socket.on("connect", () => {
// either with send()
socket.send("Hello!");
// or with emit() and custom event names
socket.emit("salutations", "Hello!", { "mr": "john" }, Uint8Array.from([1, 2, 3, 4]));
});
// handle the event sent with socket.send()
socket.on("message", data => {
console.log(data);
});
// handle the event sent with socket.emit()
socket.on("greetings", (elem1, elem2, elem3) => {
console.log(elem1, elem2, elem3);
});
Socket.IO
는 WebSocket
을 상속받은 것이 아니다.Socket.IO
는 각 패킷에 추가적인 metadata를 넣는다.WebSocket
클라이언트는 Socket.IO
서버에 접속하지 못하고,Socket.IO
클라이언트는 WebSocket
서버에 접속하지 못한다.Socket.IO
는 모바일 전용 서비스에서는 사용하면 안된다.WebSocket
연결을 할 수 없을 때는 HTTP long-polling
을 이용하기 때문에 연결에 대한 신뢰성이 있다.서버-클라이언트간 low-level 연결을 책임진다.
연결과 메커니즘 upgrade(프로토콜 전환)
disconnection 탐지
구조
Manager
은 Socket
들의 reconnect 로직을 관리한다.Socket
은 같은 Manager 인스턴스를 사용할 수도 있고, 모두 따로 사용할 수도 있다. (forceNew, multiplex 옵션, Namespaces)Manager
인스턴스를 공유하는 Socket
들은 engine options, 패킷 버퍼를 공유한다. (하나의 연결에 의존)두 가지의 연결이 있다.
HTTP long-polling
WebSocket
연결Websocket
인터페이스를 쓰지않는다.ws
/ wss
프로토콜을 사용하여 통신emit
은 자체 웹소켓 프레임으로 전송Engine.IO
연결이 시작될 때, 서버에서 다음과 같은 정보를 보낸다.
{
"sid": "FSDjX-WRwSA4zTZMALqx",
"upgrades": ["websocket"],
"pingInterval": 25000,
"pingTimeout": 20000
}
sid
는 session ID이고, 이후 모든 HTTP요청의 쿼리파라미터에 포함되어야 한다.upgrades
에는 서버에 의해 지원되는 더 나은 방식의 전송 리스트가 포함되어있다.pingInterval
과 pintTimeout
은 주기적인 신호 메커니즘에 사용된다.pingInterval
: 서버가 ping패킷을 보내는 주기pingTimeout
: 클라이언트가 ping패킷을 받고나서 pong패킷을 보내기까지의 시간HTTP long-polling
이 전송의 기본값이다.
Engine.IO
는 서버의 퍼포먼스보단 유저경험의 관점에서 더 나은 방법을 선택했다.
연결이 안 될 수도 있는 WebSocket
이 아닌 HTTP long-polling
을 default로 설정해서 연결의 신뢰성을 취한다.
다음 상황에서 Engine.IO는 연결이 끊어졌음을 인식한다.
socket.disconnect()
함수가 호출됐을 때 (서버 혹은 클라이언트에서)pong
패킷을 받지 못했거나 클라이언트에서 ping
패킷을 받지 못했을 때WebSocket
통신이 안돼도 HTTP long-polling
통신을 통해 신뢰성있는 실시간에 가까운 연결을 할 수 있다.Acknowledgements
를 통해 custom event emit을 할 수 있다.Socket.IO
를 이용해서 만들어야한다.