-
0829. HTTP 서버CS/네트워크 2023. 8. 29. 18:12
📍HTTP
문자 기반의 프로토콜로, html 문서를 전달하기 위함이다.
여기서 문자는 ASCII 문자를 말한다. *한글 처리시 문제가 생길 수 있다.
TCP가 구축된 상태에서 시작된다.(localhost:8080 부분 - 소켓역할)
포트번호 : 80 (default)
서버 주소 뒤에 콜론과 포트번호를 입력하면 해당 포트로 접속하겠다는 뜻이고,
생략하면 default로 접속하겠다는 듯이다
https의 s는 security로 보안이 더 강화된 것인데 요즘 많이 쓰는 형태이다.
접속이 되면 하나의 요청을 보내고, 서버는 이 요청을 보고 무엇인지 분석 파악 후 응답을 메모한다. 이후 연결을 끊는다.
접속에 대한 상태를 유지하지 않는 "statelss" 이다.
이러한 특성으로 웹서버의 구조가 간단하고 안정적인 것이다.
프로토콜에서 알아야 할 부분
1. 절차
2. 메시지 구조 (어떻게 해석하고 만들어낼지 중요) ❗
첫 요청일 때 어떤 형태로 문자열을 내보내야 하는지, <- 첫 번째 절차
응답 시 또 어떤 형태로 문자열을 보내는가 <- 두 번째 절차
소켓 클래스에 서버주소와 포트번호를 지정하면 불러낼 수 있으니 이제 뭘 불러낼지를 정해야 한다.
HTTP Request
개행문자가 중요한 역할을 하며 3가지 파트가 있다.
1) 요청라인 Request Line : Http method(GET 인지 POST인지) , URL(주소), 끝에 개행문자
공백을 통해 3가지 정보가 나열된다.
브라우저의 form 을 통해서 요청을 보낼 때는 GET, POST 만 쓸 수 있다.
GET : 정보 추출용 (read용) - body 없음
+) <a href=" ">, <img src=" ">도 GET 요청이고 주소가 비면 현재 사이트이다.
POST : 정보를 줘서 생성 (데이터 베이스에 저장 - create)
4개를 전부 쓰려면 자바스크립트(Ajax)를 통해 비동기 통신을 사용해야한다.
PUT : 준 정보로 수정(update)
DELETE : 이렇게 삭제해 달라는 정보 (delete) - body 없음GET이나 POST 다음 한 칸 띄우고 /bbs/index.html 2) 요청헤더 Request Header : 텍스트 기반의 통신으로 문자열이 기본이다. 빈 줄이 나올 때까지 header영역이며 각줄 끝에 개행문자가 들어간다. 콜론(:) 왼쪽은 정보(key)이고 오른쪽이 값(value). 개수제한은 없다. 왼쪽의 정보를 보고 어떤 운영체제에서 했는지 알 수 있다. readLine()으로 읽어서 \n 빈 줄(개수 제한x)이 나오면 Header가 끝났다는 뜻이다.
3) 요청본체 Request Body : 브라우저가 보내는 문자열이다. GET, DELETE으로 요청 했을 때는 body부분이 없다.
🖤 http 프로토콜의 statelss 절차
1) 접속
2) 요청(Request)
3) 응답(Response)
4) 연결 끊기
stateless : 메모리 확보, 안정성 상승 - 매번 끝날 때마다 연결을 끊어서 다시 작업을 연결해야 하는 이유
80포트로 서버 기동하기
package java_study.chapter12.http; import java.net.ServerSocket; import java.net.Socket; public class SimpleHttpServer { public static void main(String[] args) { Socket socket = null; // 서버 소켓 생성 try (ServerSocket serverSocket = new ServerSocket(80);) { System.out.println("서버 기동됨"); System.out.println("클라이언트 접속 대기 중"); while (true) { socket = serverSocket.accept(); // 접속 대기 System.out.println("클라이언트 접속 성공"); // 실제 통신은 스레드로 위임 } } catch (Exception e) { e.printStackTrace(); } } }
9090 포트
주소창에
localhost:9090/bbs/index.html 을 엔터 쳐 보자
/bbs부터 실제 요청 내용
헤더 정보는 브라우저가 알아서 전달 => 알아보려면 루프를 돌려야한다.
뭘 요청할지 모르면 기본적으로 무한루프 while(true) => 빈 줄("")이 나타날 때까지
// 2. 요청 헤더(key:value) while (true) { line = r.readLine(); if (line.equals("")) { // 헤더의 끝 break; } System.out.println(line); }
GET 요청이라 body 를 보려면 영원히 블락
HTTP Response
status Line 상태라인 : Protocol/Version 상태코드 설명
🖤 주요 상태 코드
200 : 잘 연결됨, 뒤에 설명문자열이 붙음(response Header) > 설명은 없어도 됨
400 : URL 잘못 썼다. 그런 거 없다. (클라이언트 잘못)
500 : 서버 개발자 버그로 처리하다가 예외가 발생 (서버 잘못)flush를 해야 버퍼가 비워져서 웹페이지 상에서 나타난다.
// 응답을 내보냄 HTTP Response PrintWriter w = new PrintWriter(socket.getOutputStream()); // 1) 응답 라인 w.println("HTTP/1.1 200 OK"); // 2) 헤더 w.println("Content-type: text/html"); // body를 뭐로 해석해야하는지 지정해 주는 것 html로 해석해라 w.println(); // 헤더의 끝을 나타내기 위한 빈 줄 // 3) body w.println("<html>"); w.println("<body><h1>Hello</h1></body>"); w.println("</html>"); w.flush(); socket.close();
검사 창에서 네트워크 - 새로고침하면 제대로 응답받았는지 확인 가능하다.
응답 받은 건 헤더 하나
Content-Type: text/html
원본 raw SimpleHttpServer 코드 ⬇️
더보기SimpleHttpServer
package java_study.chapter12.http; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class SimpleHttpServer { public static void main(String[] args) { Socket socket = null; // 서버 소켓 생성 try (ServerSocket serverSocket = new ServerSocket(9090);) { System.out.println("서버 기동됨"); System.out.println("클라이언트 접속 대기 중"); while (true) { socket = serverSocket.accept(); // 접속 대기 System.out.println("클라이언트 접속 성공"); BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 1. 요청라인 String line = r.readLine(); System.out.println(line); // 2. 요청 헤더(key:value) while (true) { line = r.readLine(); if (line.equals("")) { // 헤더의 끝 break; } System.out.println(line); } // 3. BODY - GET 요청일 때는 없음 // 응답을 내보냄 HTTP Response PrintWriter w = new PrintWriter(socket.getOutputStream()); // 1) 응답 라인 w.println("HTTP/1.1 200 OK"); // 2) 헤더 w.println("Content-type: text/html"); // body를 뭐로 해석해야하는지 지정해 주는 것 html로 해석해라 w.println(); // 헤더의 끝을 나타내기 위한 빈 줄 // 3) body w.println("<html>"); w.println("<body><h1>Hello</h1></body>"); w.println("</html>"); w.flush(); socket.close(); } } catch (Exception e) { e.printStackTrace(); } } }
헤더도 빼내오기
split
// 1. 요청라인 String line = r.readLine(); System.out.println(line); String[] url = line.split(" "); System.out.println("요청한 파일: " + url[1]);
이런 것들을 다 잘 빼도록 준비된 패키지가 프레임워크에 있다.
Header는 Key(왼쪽), value(오른쪽) 의 구성이므로 둘다 다루는 Map으로 쓰면 된다.
'CS > 네트워크' 카테고리의 다른 글
headers 설정할 때 User-Agent 문자열을 가져오는 법 (0) 2024.07.03