메소드 참고 링크
https://socket.io/docs/v4/emitting-events/
Emitting events | Socket.IO
There are several ways to send events between the server and the client.
socket.io
1. io객체와 socket객체를 혼동하지 말자
클라이언트
const socket = io();
socket.on("이벤트이름", (msg) => { 로직 }
서버
const io = new Server(server)
...중략...
io.on("connection", (socket) => {
socket.on("이벤트이름", (msg) => {
io.emit("chatMsg", msg)
})
})
io객체는 new Server(server)라는 대목에서도 알 수 있지만, 클라 - 서버간의 양방향 연결을 위한 가장 위에있는 객체라고 보면 될 것 같다.
따라서 클라에선 socket이라는 변수에 io()객체를 초기화 함으로서 서버와의 통신을 하도록 준비하는 것이다.
socket객체는 서버에선 io객체에서 데이터 송수신을 위한 socket객체를 callback 인자로 보내는 것을 위 코드를 통해 알 수 있다.
이 callback 함수 내에서 지지고 복고 하여 클라쪽에서 메세지 수신을 할 수 있는 것을 알 수 있다.
2. Emit
emit(=방출하다)
클라-서버 간의 데이터를 전송할 때 사용되는 메소드.
클라이언트 -> 서버
// 클라이언트
socket.emit('hello', 1, '2', { 3: '4', 5: Uint8Array.from([6]) });
// 서버
io.on('connection', (socket) => {
socket.on('hello', (arg1, arg2, arg3) => {
console.log(arg1); // 1
console.log(arg2); // '2'
console.log(arg3); // { 3: '4', 5: <Buffer 06> }
});
});
서버 -> 클라이언트
//서버
io.on("connection", (socket) => {
socket.emit("hello", "world")
})
// 클라이언트
socket.on("hello", (arg) => {
console.log(arg) // "world"
})
Note..
- Date 객체는 문자열 표현으로 변환된다. ( 1970-01-01T00:00:00.000Z )
- Map이나 Set으로 시리엉화 해주는 것이 반드시 필요하다.
const serializedMap = [...myMap.entries()];
const serializedSet = [...mySet.keys()];
- toJSON메소드로 객체의 직렬화를 하는 것을 권장한다.
class Hero {
#hp;
constructor() {
this.#hp = 42;
}
toJSON() {
return { hp: this.#hp };
}
}
socket.emit("here's a hero", new Hero());
3. Acknowledgements
3.1 emit() 메소드의 마지막 인자로, 콜백을 추가할 수 있다.
// 클라이언트
socket.timeout(5000).emit("request", {foo, "bar"}, (err, response) => {
if(err){
// 지연시간 동안(5000밀리초) 이벤트가 확인되지 않았을 때의 로직
}
else{
console.log(response)
}
})
// 서버
io.on("connection", (socket) => {
socket.on("request", (arg1, callback) => {
cosole.log(arg1) // {foo, "bar"}
callback({
status : "ok"
})
})
})
3.2 emitWithAck() 메소드는 상대방이 이벤트를 승인하면 해결되는 Promise를 반환한다.
// 클라이언트
try {
const response = await socket.timeout(5000).emitWithAct("request", {foo : "bar"})
console.log(response.status) // "ok"
}
catch(e){
}
// 서버
io.on("connection", (socket) => {
socket.on("request", (arg1, callback) => {
cosole.log(arg1) // {foo, "bar"}
callback({
status : "ok"
})
})
})
두 메소드 모두 같은 이벤트를 전송한다는 공통점이 있다..
그러면 이 두 메소드를 적재적소에 맞게 사용하려면 어떻게 해야할까?
4. Volatile events ( 휘발성 이벤트 )
아직 데이터 송수신이 준비되지 않았을 때, 버퍼링 시간같은 거 카운트하기 유용하다.
//서버
io.on("connection", (socket) => {
console.log("connect");
socket.on("ping", (count) => {
console.log(count);
});
});
//클라이언트
let count = 0;
setInterval(() => {
socket.volatile.emit("ping", ++count);
}, 1000);
1. volatile 메소드를 사용했을 때 출력결과
connect
1
2
3
4
# the server is restarted, the client automatically reconnects
connect
9
10
11
2. volatile 메소드를 사용하지 않았을 때 출력결과
connect
1
2
3
4
# the server is restarted, the client automatically reconnects and sends its buffered events
connect
5
6
7
8
9
10
11
'소켓' 카테고리의 다른 글
socket 튜토리얼 - emit 메소드와 emitWithAck 둘 중에 뭘 써야할까? (0) | 2024.05.02 |
---|---|
socket 튜토리얼 - STEP1 부터 STEP5 (0) | 2024.05.01 |