오늘 코드를 설명하기 앞서 우선 기본적인 내용을 먼저 알고 가야 할 것 같습니다
우선 가장 중요한 요점은 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 |