[JAVA / 네트워크] 멀티룸 구조에 대하여(게임&채팅 방 여러개)
Development/Java

[JAVA / 네트워크] 멀티룸 구조에 대하여(게임&채팅 방 여러개)

반응형

멀티 룸 구조라는 것에 대해 이해는 하고 있지만 구현에 애를 먹었던 기억이 있다.


이는 채팅 이라던지, 게임에 통용되는 개념으로


하나의 방을 가지는 게임과 채팅이라면 상관은 없으나, 여러개의 방을 가져야하는 프로그램에서는 구현을 해주어야 한다.


일단 접속하는 각각의 유저마다 소켓을 가지고 있을 것이다.


서버에서는 여러개의 소켓을 생성하여 클라이언트를 할당하게 되고,


그 소켓을 방(Room) 개념에 맞게 분배해주면 간단하게 구현이 된다.


예를 들어 메인 클래스가 있다고 했을 때 멀티룸 구조를 위해서 두개의 클래스가 더 필요하게 된다.


편의상 간단하게


RoomManager, GameRoom


이라는 이름으로 정한다고 가정하자.


구조는 다음과 같다.


그림이 많이 심플하긴한데.. 전달하고자 하는 의미는 전달되었으리라 믿음.


클래스는 기본적으로 총 3개가 필요하다


게임서버를 기준으로 잡았을 때(채팅서버나 게임서버나 사실 그냥 이름만 다를뿐)


RoomManager

GameRoom

GameUser


이정도가 필요하겠다.


각 클래스의 역할은 다음과 같다.


RoomManager : Room의 생성/삭제를 관리하는 클래스이다. Room을 여러개 가질 수 있음

GameRoom : 게임 내의 로직(게임 진행 관련)을 처리하기 위한 클래스이다.  GameUser를 여러개 가질 수 있음

GameUser : 클라이언트의 고유한 정보(닉네임, 아이템, 플레이어 정보 등)를 가지는 클래스이며, 중요한 것은 "소켓" 을 가지고 있어야 한다.


예를 들어 A, B , C라는 방이 있을 때


각 방에서 일어나는 일은 다른 방에서 알 필요가 없다.


A에서 두 사용자가 채팅을 하고 있을 때 A방에 속한 사용자들 끼리만 데이터를 주고받으면 된다.


이 때 채팅의 단계는 다음과 같이 이루어진다.



(유저A , 유저B, 유저 C)가 룸 A에 속해있다.


유저 A : Hello World 전송하고자 함


유저 A -> 서버로 Hello world 문자열 송신 -> 서버에서는 A가 속한 룸 클래스에 그 정보를 전달하게 됨 -> 전달받은 문자열을 A룸에 속한 사용자들에게 Broadcast(유저들이 가지고 있는 소켓 정보를 참조하면 바로 보낼 수 있다)


이런식으로 구성하게 된다면 각 방에 속한 사용자들 끼리만 데이터를 주고 받을 수 있다.


클래스를 직접 작성해서 올리는 건 다음에 하도록하고..


간단하게 이런식이면 될거같다


RoomManager


List<GameRoom> roomList;


로 게임룸의 리스트를 만들고 관리하며 방을 생성하고 지우는 함수를 구현한다.


GameRoom


List<GameUser> userList;

로 유저 리스트를 관리하고 유저가 나갔을 때 리스트에서 빼고, 접속했을 때 리스트에 넣어주면 된다.


GameUser


이 클래스에는 로그인 정보 및 닉네임 등을 가지고 있으면 된다. 게임이라면 아이템 정보들이, 채팅이라면 부가적인 채팅관련 변수들이 존재


 



그래서 서버에서 유저가 접속해서 방에 들어가는 과정을 간략하게  나타내본다면


--메인클래스--


Socket Accept 이후


Socket 객체를 GameUser 클래스로 생성을 해준다.


GameUser user = new GameUser(socket);


이후 사용자가 원하는 방에 입장하고자 입장처리를 요청하면


user.enterRoom(room); 이런식으로 룸에 입장처리를 한다.


enterRoom의 함수에는


void enterRoom(GameRoom room){

this.gameRoom = room;

}


이런식으로 GameUser가 가지고 있는 GameRoom객체를 복사해준다.


혹은 새로운 방을 생성하고자 하는 요청을 받는다면


--메인클래스--

RoomManager roomManger = new RoomManager(); // 클래스 시작 시 한번만 생성해야 한다.


GameUser user = new GameUser(socket);

GameRoom room = new GameRoom();


user.enterRoom(room);

room.enterUser(user);


roomManager.createRoom(room);


이런식으로 만들면 될 것 같다.


중요한점은 Room <-> User 간 서로 상호참조를 하고 있어야 한다는 점이고,

RoomManager는 Room의 리스트를,

GameRoom은 User의 리스트를,


가지고 있어야 한다는 것이다.


예제코드를 보도록 하자.


이런식으로 간단하게 세가지 케이스를 대상으로 샘플코드를 만들어봤다.


위에 언급한대로, Room과 User간 서로 상호참조를 하고 있으면 쉽게 유저와 룸에 접근할 수가 있다.


샘플 프로젝트의 구성은 네개의 클래스로 구성을 했다.



이런식으로 역시 한 패키지 내에 묶어서 작성을 하면 된다.


매우 기초적인 기능만 담았기 때문에 필요한 기능이 있다면 추가해서 사용하면 될 것 같다


이제 게임룸 구조, 프로토콜 구조에 대한 포스팅을 완료했기 때문에


추후에 작성될 포스팅은 "비동기 JAVA 네트워크" 에 대해 포스팅 하고자 한다.


그리고 최종적으로 앞선 포스팅들을 모두 이용한 간단한 샘플 네트워크 프로그램을 만드는 것이 목적이다.










* p.s

2017.11.30 수정

 - 많은 분들이 test class를 좀 달라고 하셔서.. 간만에 소스코드 좀 보고 파라미터와 클래스 등을 정리해서 수정.

 - test class 추가

 - 세상에나 코드가 아주 쓰레기였습니다. (죄송합니다) 이젠 완벽하진 못해도 기본기능은 하는 코드니 참고하시기 바래요

반응형