[ 2024.11.07 TIL ] TCP 정리 노트 및 socket 이슈

박지영·2024년 11월 7일
0

Today I Learned

목록 보기
75/84

정리 노트

몇몇 팀원 분들이 흐름에 대한 감을 잡기 힘들어하셔서 개인적으로 정리해서 보여드리려고 한다.

트러블 슈팅

redis의 socket 저장 문제

발단

1:1 대전 게임이기 때문에 상대방을 특정하기 쉽게 상대방의 socket을 저장해놓고 사용하려했음

문제 정의

  • redis에 저장한 socket에서 write 메소드를 찾을 수 없는 문제
    player1.socket.write is not a function.

사실 수집

  • redis에 정상적으로 저장되어 있음.

  • redis에서 꺼내서 로그를 찍어도 정상적인 소켓이 나옴

  • typeof socket -> Object로 판별

  • socket instanceof net.Socket -> false

    • 넷 소켓 객체가 아님

원인 추론

  • redis에 저장하고 꺼낼 때 socket이 메소드를 잃는 것 같다.

해결

  • redis에 socket을 직접적 저장하지 않고 식별할 속성을 추가하고 그 속성만 저장
 socket.id = uuidv4();

id 속성을 부여해서 식별할 것임

  • 결국 socket을 어딘가에는 저장해야한다 -> 전역 변수를 만들어서 인메모리로 관리할 것

  • 서버와 클라이언트가 연결을 수립하는 connection 이벤트에서 socket에 id를 부여하고
    key와 value 형태로 저장(map)

export const connectedSockets = new Map();

const onConnection = (socket) => {
  try {
    console.log(`client is Connected with ${socket.remoteAddress}:${socket.remotePort}`);
    socket.id = uuidv4();  // id 속성 저장
    connectedSockets.set(socket.id, socket); // id를 key로 사용

    socket.buffer = Buffer.alloc(0);

    socket.on('data', onData(socket));

    socket.on('end', onEnd(socket));

    socket.on('error', onError(socket));

    socket.on('close', onClose(socket, connectedSockets));
  } catch (error) {
    console.error(`커넥션 중 에러 발생`, error);
  }
};
  • redis에 socket 대신 socket.id를 저장하고 이것을 활용해서 connectedSockets에서 socket을 조회해서 사용할 것
const player1Socket = connectedSockets.get(player1.id);
const player2Socket = connectedSockets.get(player2.id);

if (player1Socket && player2Socket) {
// 게임 세션 생성
const gameId = uuidv4();
await redis.addUser(gameId, player1.id);
await redis.addUser(gameId, player2.id);
console.log('유저 등록');

player1Socket.gameId = gameId;
player2Socket.gameId = gameId;
// 매치 시작 알림 전송
const data = await createMatchStartNotification(player1Socket, player2Socket);
console.log('페이로드 생성');

const packetType = HANDLER_IDS.MATCH_START_NOTIFICATION;
const version = Config.CLIENT.VERSION;
const sequence = 0;
const buffer = serialize(packetType, sequence, data);
console.log('버퍼 생성');

player1Socket.write(buffer);
player2Socket.write(buffer);

console.log(`매칭 성공! 플레이어 ${player1.id} vs ${player2.id}`);
[2024-11-07 21:05:56] tower Excuting query: lrange
[2024-11-07 21:05:56] tower Excuting query: sadd
[2024-11-07 21:05:56] tower Excuting query: expire
[2024-11-07 21:05:56] tower Excuting query: sadd
[2024-11-07 21:05:56] tower Excuting query: expire
유저 등록
[2024-11-07 21:05:56] tower Excuting query: hset
[2024-11-07 21:05:56] tower Excuting query: expire
[2024-11-07 21:05:56] tower Excuting query: hset
[2024-11-07 21:05:56] tower Excuting query: expire
페이로드 생성
버퍼 생성
매칭 성공! 플레이어 2f89650b-6995-4866-a697-6033eb131eac vs d52bdbd0-6981-4b88-a9a4-089596506392

정상적으로 작동

profile
신입 개발자

0개의 댓글