개발자 성장 일지

2022.03.21 다양한 예외 처리

NEWDODORIPYO 2022. 3. 21. 23:00

오늘 코드를 설명하기 앞서 우선 기본적인 내용을 먼저 알고 가야 할 것 같습니다 

우선 가장 중요한 요점은 IO처리 <입출력> 시 에는 절대로!!!! throws 를 사용하지 않습니다!!!

또한 close( ) 가)가 없으면 서버가 죽어버리는 경우가 생기니 반듯이 close( )가 필요합니다 

사용 가능한 예외 처리의 종류는 try~catch finally , try with resource , @Cleanup 가 있다 

 

위 내용들을 숙지하고 코드로 다양한 예외 처리에 대해서 알아보겠습니다 !!

Client

public class FileClient {

    //bad code
    public static void main(String[] args) throws Exception {

        //소켓 연결
        Socket socket = new Socket("ip", 5555);
        //파일 준비 FileOutputStream
        FileOutputStream fos = new FileOutputStream("C:\\zzz\\copy.jpg");
        //읽기 준비 InputStream
        InputStream in = socket.getInputStream();
        //읽고 쓰기 속도
        byte[] buffer = new byte[1024*8];
        //읽기
        while(true){
            int count = in.read(buffer);
            if(count == -1){ break; }
            fos.write(buffer,0, count);
        }

        //닫기
        in.close();
        fos.close();
        socket.close();

    }
}

우선 변화가 없는 client 부분입니다 예외처리는 server에서 다룰예정이기에 client부분은 크게 중요한 부분은 없는 것 같습니다

코드 작성순서는 기본적으로 소켓 연결 -> OutputStream -> InputStream -> 읽기 위한 배열 생성 -> 읽기 위한 루프 문   -> close입니다 

 

베이스 Server

public class FileSendServer {

    //bad code
    public static void main(String[] args)throws Exception {

        //서버 소켓 준비
        ServerSocket serverSocket = new ServerSocket(5555);
        System.out.println("ready....");
        //100연결 가능하게 for문 돌림
        for (int i = 0; i < 100; i++) {
            //연결 받고
            Socket client = serverSocket.accept();
            System.out.println(client);
            //파일에 InputStream 연결
            InputStream fin = new FileInputStream("C:\\zzz\\origin.jpg");
            //OutputStream 뽑고
            OutputStream out = client.getOutputStream();
            //읽고 쓰기 8kb 속도
            byte[] buffer = new byte[1024*8];
           //읽고 쓰는 작업
            while(true){
                //fin에서 read읽고 buffer의 속도로
                int count = fin.read(buffer);
                //count가 -1 이면 멈추기
                if(count == -1){ break; }
                out.write(buffer,0, count);
            }
            //닫을 때는 마지막에 사용한 것 부터 닫기
            //닫기
            fin.close();
            out.close();
            client.close();
        }

        //닫기
        serverSocket.close();



    }
}

문제점 
서버 : 1줄로 대기가 생김 나중에 접속하는 사람은 느림
        한 명이 중간에 종료하면 throws 했기 때문에 중간에 문제가 생기면 나머지도 실행 불가능 (try~catch로 안전구역을 만들어줘야 함) 

 

try~catch finally

public class FileSendServer1 {
     //close 은 반듯이 무조건!!!! 해야함 기본중 기본
    //서버가 안죽음
    public static void main(String[] args)throws Exception {

        //서버 소켓 준비
        ServerSocket serverSocket = new ServerSocket(5555);
        System.out.println("ready....");

        for (int i = 0; i < 100; i++) {
            //변수 선언
            Socket client = null;
            InputStream fin = null;
            OutputStream out = null;
             //try = 시도
            //중간에 종료해버리면 client 는 실행이 안되고 catch로 빠짐
            //정상적으로 실행되면 Socket ,InputStream ,OutputStream 가 null 이됨
            try{
                //연결 받고
                client = serverSocket.accept();
                System.out.println(client);
                //파일에 InputStream 연결
                fin = new FileInputStream("C:\\zzz\\copy.mp4");
                //OutputStream 뽑고
                out = client.getOutputStream();

                //읽고 쓰기
                byte[] buffer = new byte[1024*8];

                while(true){
                    int count = fin.read(buffer);
                    System.out.println(count);
                    
                    if(count == -1){ break; }
                    out.write(buffer,0, count);
                }
                //close 했을때 null
                fin.close();
                fin = null;

                out.close();
                out = null;

                client.close();
                client = null;

            }
            //try에서 문제가 발생시 문제 내용을 출력?
            catch(Exception e){
                e.printStackTrace();
            }
            //null 이 아니라면 강제로 종료해버리기 finally 는 try 와 catch와 상관없이 무조건 실행됨
            finally {
                System.out.println("finally...................");
                // Socket ,InputStream ,OutputStream 이 not null 일때 close null일때는 Exception e
                //catch 에 { } 아무것도 안해주겠다...라는 뜻
                if(fin != null) try { fin.close(); }catch(Exception e){ }
                if(out != null) try { out.close(); }catch(Exception e){ }
                if(client != null) try { client.close(); }catch(Exception e){ }
            }

        }

        //닫기
        serverSocket.close();



    }
}

try with resource

<현재 자바 표준 방법>

public class FileSendServer2 {
   //finally가 없음
    //현재 자바에서 표준적인 방법
    //try with resource 방법
    //try(closeable 인터페이스)
    //try() -> ()안에 일반 변수 선언 x
    //try() 안에  AutoCloseable 코드는 자동으로 close됨
    public static void main(String[] args)throws Exception {

        //서버 소켓 준비
        ServerSocket serverSocket = new ServerSocket(5555);
        System.out.println("ready....");

        for (int i = 0; i < 100; i++) {
            //
            try(Socket client =  serverSocket.accept();
                InputStream fin =  new FileInputStream("C:\\zzz\\copy.mp4");
                OutputStream  out = client.getOutputStream();
            ){
                //연결 받고

                System.out.println(client);

                //읽고 쓰기
                byte[] buffer = new byte[1024*8];

                while(true){
                    int count = fin.read(buffer);
                    System.out.println(count);

                    if(count == -1){ break; }
                    out.write(buffer,0, count);
                }
            }catch(Exception e){
                e.printStackTrace();
            }

        }

        //닫기
        serverSocket.close();



    }
}

 이 코드에서 가장 중요한 점은 try( ) 안에 AutoCloseable 코드는 자동으로 close 가 되는 것이다 

 

lombok 너란 녀석은 참... @Cleanup

public class FileSendServer3 {

    //bad code
    public static void main(String[] args) throws Exception {
           //@Cleanup = 자동으로 try~catch finally 을 자동으로 해줌

            //서버 소켓 준비
           @Cleanup ServerSocket serverSocket = new ServerSocket(5555);
            System.out.println("ready....");
            //100연결 가능하게 for문 돌림
            for (int i = 0; i < 100; i++) {
                //연결 받고
                 @Cleanup Socket client = serverSocket.accept();
                System.out.println(client);
                //파일에 InputStream 연결
                 @Cleanup InputStream fin = new FileInputStream("C:\\zzz\\origin.jpg");
                //OutputStream 뽑고
                 @Cleanup  OutputStream out = client.getOutputStream();
                //읽고 쓰기 8kb 속도
                byte[] buffer = new byte[1024 * 8];
                //읽고 쓰는 작업
                while (true) {
                    //fin에서 read읽고 buffer의 속도로
                    int count = fin.read(buffer);
                    //count가 -1 이면 멈추기
                    if (count == -1) {
                        break;
                    }
                    out.write(buffer, 0, count);
                }

            //닫기
            serverSocket.close();

        }
    }
}

 사용해본 lombok의 기능들 중 가장 편하다고 느껴지는 부분이 아니었나 생각해본다 위에서 만들어본 try~catch finally 나 try with resource 코드는 기능이나 안정성 면에서는 우월하지만 코드가 복잡해지고 많아졌는데 lombok의 @Cleanup을 사용하니 그런 기능적인 면도 챙기고 코드도 짧아졌습니다 

'개발자 성장 일지' 카테고리의 다른 글

2022.03.23 채팅 IO  (0) 2022.03.23
2022.03.23 IO를 활용한 파일 보내기  (0) 2022.03.23
2022.03.21 예외 처리  (0) 2022.03.21
2022.03.18 입출력 속도  (0) 2022.03.20
2022.03.17 수업 정리< 입출력 용어 정리 >  (0) 2022.03.20