[IP 주소, Port] VerySimpleWebServer

ho's·2022년 6월 8일
0

🍔 IP 주소, Port

  • 127.0.0.1 은 자신의 IP를 말한다.

🍟 도메인 네임 서버(Domain Name Server: DNS)

  • 도메인 주소를 IP로 변환한다.
  • nslookup 도메인주소
    위의 명령으로 도메인에 해당하는 IP주소를 알아 낼 수 있다.

🍤 IP주소 알아내기

  • InetAddress로 알아낸다.
  • 사용자 컴퓨터의 IP주소 알아내기
InetAddress ia = InetAddress.getLocalHost();
System.out.println(ia.getHostAddress());
  • google의 IP주소 알아내기
	InetAddress[] iaArr = InetAddress.getAllByName("www.google.com");
    for(InetAddress ia : iaArr){
    	System.out.println(ia.getHostAddress());
    }

🍤 내 PC IP 주소 알아내기 예시

public class IpAddressExam {
    public static void main(String[] args) {
        try {
            InetAddress ia = InetAddress.getLocalHost(); // 내 정보의 IP정보를 구한다.
            // getLocalHost 는 InetAddress객체를 반환한다.
            System.out.println(ia.getHostAddress());
        }catch(UnknownHostException uhe){
            uhe.printStackTrace();
        }
    }
}

🍟 Client & Server 프로그래밍

  • Socket : Server에 접속을 하는 역할

  • ServerSocket : Client가 접속 요청을 기다리는 역할
    Client 요청을 기다리다가 접속을 하면 Socket을 반환한다.

  • Socket과 Socket간에는 IO객체를 이용하여 통신할 수 있다.

🍤 HTTP 프로토콜

🍟 TCP(Transmission Control Protocol)

특징

  • 연결지향 프로토콜 -> 시간 소요가 된다.
  • 통신 선로 고정 -> 전송 속도가 느려진다.
  • 데이터를 정확하고 안정적으로 전달

java.net API

  • ServerSocket, Socket

🍤 ServerExample 예제

package net;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerExample {
    public static void main(String[] args){

        ServerSocket serverSocket = null;
        try{
            // 서버 소켓 객체 만들기.
            serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress("localhost", 9090));

            // 서버는 항상 클라이언트의 요청을 기다려야 한다.
            while(true){
                System.out.println("[연결 기다림]");
                // 서버 소켓의 객체를 만들어서, 기다린다.
                Socket socket = serverSocket.accept();
                InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
                System.out.println("연결 수락함." + isa.getHostName());
            }
        }catch(Exception e){
            e.printStackTrace();
        }

        // 서버가 닫혀있지 않다면 닫히는 코드
        if(!serverSocket.isClosed()){
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

🍤 ClientExample 예제


import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

public class ClientExample {
	public static void main(String[] args) {
		
        // Socket 변수 선언
        Socket socket = null;
        
        try{
        	// socket 생성
            socket = new Socket();
            System.out.println("[연결 요청]");
            socket.connect(new InetSocketAddress("localhost", 9090));
            System.out.println("연결 성공");
        } catch(Exception e){
        	e.printStackTrace();
        }
        
        if(!socket.isClosed()){
        	try{
            	socket.close();
            } catch(IOException e){
            }
        }
	}
}

제대로 작동하기 위해서는 위의 그림 처럼, Server를 먼저 실행 시켜야 한다.

server 클래스 실행시 결과

client 클래스 실행시 결과

🍟 브라우저 요청 결과를 출력하는 Server 프로그램 작성하기

  • http://ip:port 주소로 브라우저는 요청을 보낼 수 있다.
  • ServerSocket은 특정 port로 접속 요청을 기다릴 수 있다.
  • 브라우저는 서버와 연결이 되면 요청 정보를 전송한다.
  • 서버는 브라우저가 보내는 요청정보를 읽어 들인 후, 그 결과를 출력 할 수 있다.

🍤 Socket 생성과 연결 요청

try{
	Socket socket = new Socket("localhost", 5001); // 방법1
    Socket socket = new Socket(new InetSocketAddress("localhost", 5001)); // 방법2
} catch(UnknownHostException e){
		// IP 표기 방법이 잘못 되 었을 경우
} catch(IOException e){
	// 해당 포트의 서버에 연결 할 수 없는 경우
}

🍤 Socket 끊기요청

try{
	socket.close();
} catch(IOException e) {}

🍤 소스코드

package net;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class VerySimpleWebServer {
    public static void main(String[] args) throws Exception {

        // 9191 port로 대기한다.
        ServerSocket ss = new ServerSocket(9191);
        // 클라이언트를 대기
        // 클라이언트가 접속하는 순간, 클라이언트와 통신할 수 있는 socket을 반환한다.
        // http://127.0.0.1:9191/board/hello.html 왼쪽과 같이 입력받았다고 하자.
        System.out.println("클라이언트 접속을 기다립니다.");
        Socket socket = ss.accept();

        System.out.println(socket.toString());
        OutputStream out = socket.getOutputStream();
        InputStream in = socket.getInputStream();
        // HTTP 프로토콜은 클라이언트가 정보를 서버에 보내준다.( 요청 정보)
        byte[] buffer= new byte[512];
        int readCount = 0;

        while((readCount = in.read(buffer)) != -1){
            System.out.write(buffer,0, readCount);
        }
        System.out.println(socket.toString());

        ss.close();
        System.out.println("클라이언트 종료.");
    }
}


위와 같이 브라우저에서 서버로 연결신청을 했기 때문에 서버 소켓을 통해 읽어 들였다.

결과는..

빈줄까지 읽어야 끝이 난다!!

이 말은 위의 코드 중while((readCount = in.read(buffer)) != -1) 와 같이 코드를 작성하면 안 된다는 것이다. 한 줄씩 읽어들이는 코드를 작성해 보자.

🍤 한 줄씩 읽는 코드를 작성해 보자.

package net;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class VerySimpleWebServer {
    public static void main(String[] args) throws Exception {

        // 9191 port로 대기한다.
        ServerSocket ss = new ServerSocket(9191);
        // 클라이언트를 대기
        // 클라이언트가 접속하는 순간, 클라이언트와 통신할 수 있는 socket을 반환한다.
        // http://127.0.0.1:9191/board/hello.html 왼쪽과 같이 입력받았다고 하자.
        System.out.println("클라이언트 접속을 기다립니다.");

        Socket socket = ss.accept();

        OutputStream out = socket.getOutputStream();
        InputStream in = socket.getInputStream();
        // HTTP 프로토콜은 클라이언트가 정보를 서버에 보내준다.( 요청 정보)
        BufferedReader br = new BufferedReader(new InputStreamReader(in));

        //가장 중요한 Line!
        String firstLine = br.readLine();
        // 줄바꿈 부터, List에 담는다.
        List<String> headers = new ArrayList<>();
        // 빈줄이 나올때 까지 읽어 들이자!
        // 빈 줄을 만나면 while 문을 끝내자.
        String line = null;
        while(!(line = br.readLine()).equals("")){
            headers.add(line);
        }
        // 요청정보 읽기가 끝난다.
        System.out.println(firstLine);
        for(int i=0;i<headers.size();i++){
            System.out.println(headers.get(i));
        }
        ss.close();
        System.out.println("클라이언트 종료.");
        
    }
}

🍤 HTTP 프로토콜 응답메세지

  • 서버에게 응답 메세지 보내기
  • 첫번째 줄은 상태메세지: HTTP/1.1 200 OK <-- 상태 메세지
  • 헤더 1
  • 헤더 2
  • 빈줄
  • 내용

PrintWriter, OutputStream을 통해 Server에 응답메세지를 보내자.

package net;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class VerySimpleWebServer {
    public static void main(String[] args) throws Exception {

        // 9191 port로 대기한다.
        ServerSocket ss = new ServerSocket(9191);
        // 클라이언트를 대기
        // 클라이언트가 접속하는 순간, 클라이언트와 통신할 수 있는 socket을 반환한다.
        // http://127.0.0.1:9191/board/hello.html 왼쪽과 같이 입력받았다고 하자.
        System.out.println("클라이언트 접속을 기다립니다.");

        Socket socket = ss.accept();

        OutputStream out = socket.getOutputStream();
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
        InputStream in = socket.getInputStream();
        // HTTP 프로토콜은 클라이언트가 정보를 서버에 보내준다.( 요청 정보)
        BufferedReader br = new BufferedReader(new InputStreamReader(in));

        //가장 중요한 Line!
        String firstLine = br.readLine();
        // 줄바꿈 부터, List에 담는다.
        List<String> headers = new ArrayList<>();
        // 빈줄이 나올때 까지 읽어 들이자!
        // 빈 줄을 만나면 while 문을 끝내자.
        String line = null;
        while(!(line = br.readLine()).equals("")){
            headers.add(line);
        }
        // 요청정보 읽기가 끝난다.
        System.out.println(firstLine);
        for(int i=0;i<headers.size();i++){
            System.out.println(headers.get(i));
        }

        pw.println("HTTP/1.1 200 OK");
        pw.println("name : kim");
        pw.println("email: daeeho@naver.com");
        pw.println();
        pw.println("<html>");
        pw.println("<h1>Hello!!</h1>");
        pw.println("</html>");
        pw.close();

        ss.close();
        System.out.println("서버 종료.");
    }
}

profile
그래야만 한다

0개의 댓글