[포스코DX|Java|3주] 9일차 수업
포스코DX X 비트교육센터 6기 - 웹서버 / 채팅
자바의 웹
JavaEE의 Servlet과 서블릿 실행시키는 Servelet container(=WAS)스택이 실행시켜줌
- 요청한 자료가 없을 경우, 404에러 발생 ex) local:8088/얍/얍 -» 404에러 해당 url을 가진곳에 대한 설정이 없음.
localhost
webapp - url mapping
webapp은 url의 / 를 의미하고, localhost:8088/assets/images/profile.jpg로 접근하면, /webapp밑의 파일들에 접근하는 것이다.
웹 CRUD
GET (=read, 자원읽기) POST (=create, 자원생성) PUT (=update, 자원수정) DELETE (=자원삭제)
url mapping
private void responseStaticResource(OutputStream outputStream, String url, String protocol) throws IOException {
// default(welcome) file
if ("/".equals(url)) {
url = "/index.html";
}
File file = new File(DOCUMENT_ROOT + url);
if (!file.exists()) {
System.out.println("404 File NOT Found: " + url);
// responseStatic404Error(outputStream, tokens[2]);
return;
}
// nio
byte[] body = Files.readAllBytes(file.toPath());
String contentType = Files.probeContentType(file.toPath());
// 응답
outputStream.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8"));
outputStream.write(("Content-Type:" + contentType + "; charset=utf-8\r\n").getBytes("UTF-8"));
outputStream.write("\r\n".getBytes());
outputStream.write(body);
}
400에러(post error), 404에러(not page/resourse error)
private void responseStatic400Error(OutputStream outputStream, String string) {
// post 에러
// HTTP/1.1 404 File Not Found\r\n
// Content-Type:text/html; charset=utf-8\r\n
//\r\n
// error/404.html 내용
}
private void responseStatic404Error(OutputStream outputStream, String protocol) throws IOException {
// 없는 페이지 에러
// HTTP/1.1 404 File Not Found\r\n
// Content-Type:text/html; charset=utf-8\r\n
//\r\n
// error/404.html 내용
outputStream.write("HTTP/1.1 404 File Not Found\\r\\n".getBytes("UTF-8"));
outputStream.write("Content-Type:text/html; charset=utf-8\r\n".getBytes("UTF-8"));
outputStream.write("\r\n".getBytes());
outputStream.write("<h1>404 Error</h1>".getBytes("UTF-8"));
}
채팅
chatServer, chatServerThread, chatClient, chatClientThread
- 포트 : 9999
- 클라이언트가 Thread인 이유? nextLine() / readLine() 두가지 blocking이 필요. => 다른 사용자의 메시지는 키보드로 입력도중에 전달되어 화면에 출력된다.
- 서버는 accept와 readLine 두가지 blocking이 필요해서 thread가 필요하다.
- base64 엔코딩(클라쪽) 디코딩(서버쪽) - 암호화가 아님! 그럼 왜 해?
Binary 데이터를 텍스트 기반 규격으로 다룰 수 있기 때문이다.
JSON과 같은 문자열 기반 데이터 안에 이미지 파일등을 Web에서 필요로 할때 Base64로 인코딩하면 UTF-8과 호환 가능한 문자열을 얻을 수 있다.
끝에 '='과 같은 패딩 기호가 있다면 이는 구분자로써 사용되므로 대부분 Base64로 생각할 수 있다.
기존 ASCII 코드는 시스템간 데이터를 전달하기에 안전하지 않다.
모든 Binary 데이터가 ASCII 코드에 포함되지 않으므로 제대로 읽지 못한다.
반면 Base64는 ASCII 중 제어문자와 일부 특수문자를 제외한 53개의 안전한 출력 문자만 이용하므로 데이터 전달에 더 적합하다.
- 여기에 닉네임이 포함된 이유? 방참여 할 때마다 (=서버 스레드 추가됟ㄹ때마다) “닉네임님이 참여합니다.” 라는 메시지를 보내기 때문.
정리
- 서버 쓰레드와 클라 소켓 연결
- 사용자가 둘리 입력
- 클라가 서버 쓰레드(br, printWriter)로 “둘리”를 담음
- 클라 쓰레드를 만듦. 클라 소켓은 printwirter로 nextLine을 가지고 기다리며, 클라 쓰레드 소켓은 br.readline을 가지고 각자 무한 루프되고있음.
- 서버는 accept하기 전에 리스트를 만듦. List
accept가 들어오자마자 서버 쓰레드에 값이 들어오면 List와 쓰레드에 pw1값으로 생성 - 사용자가 안녕 하고 엔터를 누르면 클라 쓰레드에 안녕이 담기고 서버 쓰레드에 둘리:안녕 string으로 저장함.
- 방을 나가면 ,쓰레드에서 둘리님이 나갔습니다. 뜨고 List.remove(pw1);, List 순회하며 둘리님이 나감을 알린다. 그리고 둘리쓰레드가 close되면서 무한 루프를 나온다.
필요한 기능 3가지
- join
- 메시지 보내고
- 나가기