포스코DX X 비트교육센터 6기 - 웹서버 / 채팅


CharlieBrownSnoopyGIF (2)

자바의 웹

JavaEE의 Servlet과 서블릿 실행시키는 Servelet container(=WAS)스택이 실행시켜줌

  • 요청한 자료가 없을 경우, 404에러 발생 ex) local:8088/얍/얍 -» 404에러 해당 url을 가진곳에 대한 설정이 없음.

localhost

image

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"));
	}

채팅

image

chatServer, chatServerThread, chatClient, chatClientThread

image

  • 포트 : 9999
  • 클라이언트가 Thread인 이유? nextLine() / readLine() 두가지 blocking이 필요. => 다른 사용자의 메시지는 키보드로 입력도중에 전달되어 화면에 출력된다.
  • 서버는 accept와 readLine 두가지 blocking이 필요해서 thread가 필요하다.

image

  • base64 엔코딩(클라쪽) 디코딩(서버쪽) - 암호화가 아님! 그럼 왜 해?
Binary 데이터를 텍스트 기반 규격으로 다룰 수 있기 때문이다.
JSON과 같은 문자열 기반 데이터 안에 이미지 파일등을 Web에서 필요로 할때 Base64로 인코딩하면 UTF-8과 호환 가능한 문자열을 얻을 수 있다.
끝에 '='과 같은 패딩 기호가 있다면 이는 구분자로써 사용되므로 대부분 Base64로 생각할 수 있다.  

 

기존 ASCII 코드는 시스템간 데이터를 전달하기에 안전하지 않다.
모든 Binary 데이터가 ASCII 코드에 포함되지 않으므로 제대로 읽지 못한다.
반면 Base64는 ASCII 중 제어문자와 일부 특수문자를 제외한 53개의 안전한 출력 문자만 이용하므로 데이터 전달에 더 적합하다.

image

  • 여기에 닉네임이 포함된 이유? 방참여 할 때마다 (=서버 스레드 추가됟ㄹ때마다) “닉네임님이 참여합니다.” 라는 메시지를 보내기 때문.

정리

  1. 서버 쓰레드와 클라 소켓 연결
  2. 사용자가 둘리 입력
  3. 클라가 서버 쓰레드(br, printWriter)로 “둘리”를 담음
  4. 클라 쓰레드를 만듦. 클라 소켓은 printwirter로 nextLine을 가지고 기다리며, 클라 쓰레드 소켓은 br.readline을 가지고 각자 무한 루프되고있음.
  5. 서버는 accept하기 전에 리스트를 만듦. List accept가 들어오자마자 서버 쓰레드에 값이 들어오면 List와 쓰레드에 pw1값으로 생성
  6. 사용자가 안녕 하고 엔터를 누르면 클라 쓰레드에 안녕이 담기고 서버 쓰레드에 둘리:안녕 string으로 저장함.
  7. 방을 나가면 ,쓰레드에서 둘리님이 나갔습니다. 뜨고 List.remove(pw1);, List 순회하며 둘리님이 나감을 알린다. 그리고 둘리쓰레드가 close되면서 무한 루프를 나온다.

필요한 기능 3가지

  • join
  • 메시지 보내고
  • 나가기

image