서버측 설계 - Server 클래스

목차

    1. 흐름

    public static void main(String[] args) {
        Server server = new Server();
        server.openFrame();
    }
    // 프레임 띄우기
    public void openFrame() {
        serverFrame = new ServerFrame(this);
        logBoard = serverFrame.getLogPanel().getLogBoard();
    }

    실행시 프레임을 띄우고 프레임의 logBoard를 받아온다. logBoard는 로그가 업데이트 되는 곳이고, server측에서 로그를 작성하기 위해서는 textArea의 컴포넌트에 접근하는 주소가 필요하다.

    // 서버 세팅 - 포트 번호 할당
    public void setupServer(int port) {
        try {
            serverSocket = new ServerSocket(port);
            logMessage("[알림] 서버 시작\n");
    
            connectClient();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    프레임 단에서 포트 번호를 입력하고 서버 생성 버튼을 누르면 호출되는 메서드.

    해당 포트번호로 서버소켓을 열고 connectClient() 호출

    // 클라이언트 연결 대기
    private void connectClient() {
        new Thread(() -> {
            while (true) {
                try {
                    logMessage("[알림] 사용자 접속 대기\n");
                    new User(this, serverSocket.accept());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    서버 소켓으로 클라이언트가 접속하길 기다리고, 접속시 User 객체를 생성 → while문을 통해 반복

    2. 기본 메서드

    // 로그 메세지 화면에 출력 + 로그 저장
    public void logMessage(String str) {
        try (PrintWriter printWriter = new PrintWriter(new FileWriter("secret_Talk_log.txt", true), true)) {
            logBoard.append(str);
            printWriter.print(str);
            printWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    서버 프레임의 textArea에 로그를 출력하는 메서드 + txt파일에 기록

    // 유저 관리를 위한 유저 리스트 추가 제거
    public void addUser(User user) {
        userList.add(user);
        userIds.add(user.getUserId());
        serverFrame.getUserListPanel().getUserList().setListData(userIds);
    }
    
    public void removeUser(User user) {
        userList.remove(user);
        userIds.remove(user.getUserId());
        serverFrame.getUserListPanel().getUserList().setListData(userIds);
    }

    유저 리스트 관리를 위한 메서드, User 객체가 직접 호출 하여 자신을 추가하거나 제거하는 방식

    // id가 이미 사용중임을 확인
    public boolean isNew(String userId) {
        for (String string : userIds) {
            if (string.equals(userId)) {
                return false;
            }
        }
        return true;
    }

    새로운 유저가 접속했을때 입력한 id가 중복인지 확인 하는 메서드

    // 접속중인 모든 유저에게 방송
    public void broadCast(String msg) {
        for (int i = 0; i < userList.size(); i++) {
            // 유저의 writer는 각각의 클라이언트로 보내는 아웃풋 스트림
            (userList.elementAt(i)).getWriter().println(msg);
        }
    }

    모든 유저의 outputStream으로 문자열을 보냄

    3. 버튼 상호작용 콜백 메서드

    @Override
    public void clickKickBtn(String userId) {
        for (int i = 0; i < userList.size(); i++) {
            User user = userList.elementAt(i);
            if (userId.equals(user.getUserId())) {
                user.logOutUser();
                user.getWriter().println("kick/" + user.getId());
            }
        }
    }

    강퇴 버튼 입력시 호출되는 메서드. userList에서 해당 user 제거 후 logOutUser() 메서드 호출, 클라이언트에 메세지 보냄

    @Override
    public void clickPersonalMsgBtn(String id, String msg) {
        for (int i = 0; i < userList.size(); i++) {
            User user = userList.elementAt(i);
            if (id.equals(user.getUserId())) {
                user.getWriter().println("personalMsg/" + "서버관리자/" + msg);
                logMessage("[메세지] 개인 메세지 : 서버관리자 -> " + id + " : " + msg + "\n");
                return;
            }
        }
    }

    개인 메세지 버튼 입력시 호출되는 메서드.  해당하는 user를 찾아 메세지를 보냄

    @Override
    public void clickGroupMsgBtn(String msg) {
        for (int i = 0; i < userList.size(); i++) {
            User user = userList.elementAt(i);
            user.getWriter().println("groupMsg/" + "서버관리자/" + msg);
            logMessage("[메세지] 단체 메세지 : 서버관리자  : " + msg + "\n");
        }
    }

    단체 메세지 버튼 입력시 호출되는 메서드. 모든 user에게 메세지를 보냄