본문 바로가기
인턴

[인턴 OJT 21일차] RMI 채팅, RackView 코드리뷰

by 리잼 2023. 1. 11.
반응형

 

채팅 RMI 흐름

 

1. 서버 실행 registry 포트 지정 레지스트이름과 함께 Remote객체(interface 상속받은 impl) bind

2. 클라이언트 실행(RMI 활성화)

	private void initRmi() throws Exception {					// RMI 활성화
		user = JOptionPane.showInputDialog("대화명을 입력하세요");
		LOGGER.debug(String.format("접속 유저 :  %s" , user));
		jTextField_User.setText(user);
		
		ClientMain.eventQueueWorker.addEventListener(this);
		
		clientIf = new ClientImpl();
		
		Registry registry = LocateRegistry.getRegistry(ServerMain.PORT);
				
		Remote remote = registry.lookup(ServerMain.BIND_NAME);
		if (remote instanceof ServerInterface) {
			serverIf = (ServerInterface)remote;
		}
	}
 

3. user이름 작성 후 토글버튼으로 접속 > user명과 clientIf 서버로 전송

ServerImpl.java

	@Override
	public void register(String name, ClientInterface clientInterface) throws RemoteException {
		LOGGER.debug(String.format("%s 님 로그인", name));
		synchronized (clientRepo) {
			clientRepo.put(name, clientInterface);
		}
	}
	@Override
	public void deregister(String name) throws RemoteException {
		LOGGER.debug(String.format("%s 님 로그아웃", name));
		synchronized (clientRepo) {
			clientRepo.remove(name);
		}
		// 지워준다.
	}

	@Override // 메세지를 Client로 보냄
	public void send(String name, String msg) throws RemoteException {
		LOGGER.debug(String.format("Server send name : [%s] msg : [%s]",name, msg));
		
		synchronized (clientRepo) {
			for (ClientInterface oneClient : clientRepo.values()) {
				oneClient.push(String.format("[%s]:%s", name, msg));
			}
		}
	}

 

 

4. send요청이 들어가면 -> ServerImpl에 send메서드를 통해 ( remote ) ClientInterface 전송

ClientInterface를 상속받은 push가 Queue로 값을 넘겨준다

5. messageRepository에 메시지를 담아두었다가 들어온 순서대로 하나씩 Client에 전송

다시 Clientimpl로 push받은 메시지를 서버에서 사용자에게 보내 JTextArea에 append 함으로서 모든 사용자의 JTextArea에 노출 후 남은 값이 있는지 쓰레드가 확인

 

QueueWorker.java

    public void push(T t) {
    	LOGGER.debug("=====Queue Worker PUSH=====", t);
		messageRepository.add(t);	// 입력된 메세지 리스트에 추가
		synchronized (waitObject) {
			waitObject.notify();  	// 기다리던 객체를 꺠운다
		}
    }

    public void run() {
        T t = null;
        runFlag = true;
        LOGGER.debug("쓰레드 시작");
        while ( runFlag ) {
            synchronized ( waitObject ) {
                if ( messageRepository.size() > 0 ) {	// 입력된 메세지가 하나 이상이면 지워준다
                    t = messageRepository.remove(0);
                }
                else {									// 메세지가 없으면
                    t = null;

                    try {
                        waitObject.wait();				// 계속 대기
                    }
                    catch ( Exception ex ) {
                        ex.printStackTrace();
                    }
                }
            }

            try {
                if ( t != null ) {
                	try{ 
                		processObject(t);
                	} catch(Exception e ) {
                		e.printStackTrace();
                	}
                }
            }
            catch ( Exception ex ) {
                ex.printStackTrace();
            }
        }
    }
 

RackView Queue

RackView Queue 흐름

서버 실행 > 클라이언트 실행 > Remote된 데이터 불러옴 > client register 서버에 등록 > serverImpl 동작 >

서버register에서 initAlarmGenerator 실행 > clientinterface push > Clinetimpl > Queue > 100개받고 쓰레드가 돌아감

 

가급적 init은 컴포넌트 > 이벤트 순으로 실행순서를 지킬 수 있도록 한다

또한 기능별로 따로 분리해야한다

private void initConnection() {
		try {			
			ClientInterface client = new ClientImpl(this);
			Registry registry = LocateRegistry.getRegistry(ServerMain.PORT);

			Remote remote = registry.lookup(ServerMain.BIND_NAME);
			
			if (remote instanceof ServerInterface) {
				serverIf = (ServerInterface) remote;
			}
			serverIf.register(client);
			
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		} LOGGER.debug("보드사이즈ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ"+boardList.size());
	}
 

 

 

QueueWorker.java

	public void push(T t) {
		LOGGER.debug("=====Queue Worker PUSH=====", t);
		messageRepository.add(t); 				// 입력된 메세지 리스트에 추가
		synchronized (waitObject) {
			waitObject.notify(); 			// 기다리던 객체를 꺠운다
		}
	}


public void run() {
        T t = null;
        runFlag = true;
        LOGGER.debug("쓰레드 시작");
        while ( runFlag ) {
            synchronized ( waitObject ) {
            	 try {
					Thread.sleep(1000);				// 1초에 하나씩 큐를 가져옴
				} catch (Exception e) {
         		LOGGER.error(e.getMessage(), e);
				}
                if ( messageRepository.size() > 0 ) {	// 입력된 메세지가 하나 이상이면 지워준다
                   
                    LOGGER.debug(String.format("버퍼 사이즈 %s", getBufferSize()));
                	t = messageRepository.remove(0);	// 먼저 들어온 순서대로 삭제
                }
                else {									// 메세지가 없으면
                    t = null;

                    try {
                        waitObject.wait();				// 계속 대기
                    }
                    catch ( Exception ex ) {
                        ex.printStackTrace();
                    }
                }
            }

            try {
                if ( t != null ) {
                	try{ 
                		processObject(t);
                	} catch(Exception e ) {
                		e.printStackTrace();
                	}
                }
            }
            catch ( Exception ex ) {
                ex.printStackTrace();
            }
        }
    }
RackView Sequence
반응형