ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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
Designed by Tistory.