관리자 글쓰기

🤷‍♂️WebSocket이란?

-> WebSocket은 실시간 데이터 전송을 위한 프로토콜이다. 기존 HTTP 프로토콜에서 한 번의 연결에 한 번의 요청/응답 방식에서 벗어나, 양 방향 통신이 가능하도록 한다.

WebSocket을 사용하는 게임 플레이어의 실시간 방 참여를 활성화하려면 다음을 수행해야 한다.

1. 클라이언트와 서버 간에 WebSocket 연결을 설정한다.

Java에서 WebSocket 클라이언트서버 간의 연결을 구현하는 예제 코드

🙌 1-1 서버

import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.Session;
import javax.websocket.OnOpen;
import javax.websocket.OnClose;
import javax.websocket.CloseReason;

@ServerEndpoint("/websocket")
public class WebSocketServer {
   @OnMessage
   public void onMessage(String message, Session session) {
      // 수신된 메시지를 처리하는 코드
   }

   @OnOpen
   public void onOpen(Session session) {
      // 연결이 열리면 처리하는 코드
   }

   @OnClose
   public void onClose(Session session, CloseReason closeReason) {
      // 연결이 닫히면 처리하는 코드
   }
}

 

🙌1-2 클라이언트

import javax.websocket.OnMessage;
import javax.websocket.ClientEndpoint;
import javax.websocket.OnOpen;
import javax.websocket.OnClose;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;

@ClientEndpoint
public class WebSocketClient {
   @OnMessage
   public void onMessage(String message) {
      // 수신된 메시지를 처리하는 코드
   }

   @OnOpen
   public void onOpen(Session session) {
      // 연결이 열리면 처리하는 코드
   }

   @OnClose
   public void onClose(Session session, CloseReason closeReason) {
      // 연결이 닫히면 처리하는 코드
   }

   public static void main(String[] args) {
      WebSocketContainer container = ContainerProvider.getWebSocketContainer();
      try {
         Session session = container.connectToServer(WebSocketClient.class, "ws://localhost:8080/websocket");
         //

 

 

2. 서버측 코드를 구현하여 연결된 클라이언트 및 해당 룸 할당을 추적한다.

🙌2-1 Java에서 WebSocket 클라이언트와 서버 간의 연결을 관리하는 예제 코드

import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.OnClose;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.Session;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint("/websocket/{room}")
public class WebSocketServer {
   private static final Map<String, Session> sessions = new ConcurrentHashMap<>();

   @OnMessage
   public void onMessage(String message, Session session) {
      // 수신된 메시지를 처리하는 코드
      String room = (String) session.getUserProperties().get("room");
      sessions.keySet().stream()
              .filter(s -> s.startsWith(room))
              .filter(s -> !s.equals(session.getId()))
              .forEach(s -> {
                 try {
                    sessions.get(s).getBasicRemote().sendText(message);
                 } catch (Exception e) {
                    // 예외 처리
                 }
              });
   }

   @OnOpen
   public void onOpen(Session session) {
      // 연결이 열리면 처리하는 코드
      String room = (String) session.getPathParameters().get("room");
      session.getUserProperties().put("room", room);
      sessions.put(session.getId(), session);
   }

   @OnClose
   public void onClose(Session session) {
      // 연결이 닫히면 처리하는 코드
      sessions.remove(session.getId());
   }
}

 

3. 룸에 참여하거나 룸에서 나가기 위해 서버에 메시지를 보내는 클라이언트측 코드를 구현한다.

🙌3-1 룸에 참여하거나 룸에서 나가기 위해 서버에 메시지를 보내는 클라이언트 측 코드 예시

import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.OnOpen;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.ContainerProvider;
import javax.websocket.WebSocketContainer;
import java.net.URI;

@ClientEndpoint
public class WebSocketClient {
   private Session session;
   private URI uri;

   public WebSocketClient(URI uri) {
      this.uri = uri;
   }

   @OnOpen
   public void onOpen(Session session) {
      this.session = session;
   }

   @OnClose
   public void onClose(CloseReason reason) {
      this.session = null;
   }

   @OnMessage
   public void onMessage(String message) {
      // 수신된 메시지를 처리하는 코드
   }

   public void connect() {
      WebSocketContainer container = ContainerProvider.getWebSocketContainer();
      try {
         container.connectToServer(this, uri);
      } catch (Exception e) {
         // 예외 처리
      }
   }

   public void sendMessage(String message) {
      if (session != null && session.isOpen()) {
         try {
            session.getBasicRemote().sendText(message);
         } catch (Exception e) {
            // 예외 처리
         }
      }
   }
}

 

4. 서버에서 브로드캐스트 룸은 같은 방에 있는 연결된 모든 클라이언트에 업데이트 된다.

🙌4-1 서버에서 브로드캐스트 룸같은 방에 있는 연결된 모든 클라이언트에 업데이트 되도록 예시 코드

private void broadcastMessage(String room, String message) {
    Set<WebSocket> roomClients = rooms.get(room);
    for (WebSocket client : roomClients) {
        try {
            client.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. 클라이언트에서 회의실 업데이트 메시지를 수신하고 실시간으로 변경 사항을 반영하도록 UI를 업데이트 한다.

🙌5-1 클라이언트에서 회의실 업데이트 메시지를 수신하고 실시간으로 변경 사항을 반영하는 예시 코드

private WebSocket webSocket;

public void start() {
    webSocket = new WebSocketFactory().createSocket("ws://example.com/chat");
    webSocket.addListener(new WebSocketAdapter() {
        @Override
        public void onTextMessage(WebSocket websocket, String message) {
            // Update the UI with the new chat room information
            updateRoomUI(message);
        }
    });
    webSocket.connect();
}

private void updateRoomUI(String message) {
    // Parse the message to get the updated room information
    // ...

    // Use the updated room information to update the UI
    // ...
}

 

이 접근 방식을 사용하면 각 방에 있는 플레이어 수를 실시간으로 업데이트 하고 플레이어가 실시간으로 방에 들어가거나 나갈 수 있다.