자바 스터디

[자바의 정석] CH 16

changha. 2023. 8. 19. 10:47

네트워킹

두 대 이상의 컴퓨터를 케이블로 연결하여 네트워크를 구성하는 것을 말한다.

 

1. 클라이언트/서버(client/server)

클라이언트 : 서비스를 사용하는 컴퓨터

서버 : 서비스를 제공하는 컴퓨터 

서비스의 종류에 따라 파일서버, 메일서버, 어플리케이션 서버 등이 있다.

 

서버기반 모델 : 네트워크를 구성할 때 전용서버를 두는 것

P2P 모델 : 별도의 전용서버없이 각 클라이언트가 서버역할을 동시에 수행하는 것 

 

 

1.5 URLConnection 

어플리케이션과 URL간의 통신연결을 나타내는 클래스의 최상위 클래스로 추상클래스

이다. 

URLConnection을 상속받아 구현한 클래스로는 HttpURLConnection과 JarURLConnection이 있다. 

 

 

public class NetworkEx3 {

    public static void main(String[] args) throws IOException {
        URL url = null;
        BufferedReader input = null;
        String address = "http://localhost:8080/";
        String line = "";

        url = new URL(address);
        input = new BufferedReader(new InputStreamReader(url.openStream()));

        while((line=input.readLine()) != null){
            System.out.println(line);
        }
        input.close();
    }
}

위 코드는 내가 작동시키고 있는 페이지를 가져오고 있다. 

네이버를 가져오려니까 작동이 안돼서 chatGPT에게 물어봤다

- gpt

주어진 코드는 기본적으로 네이버 웹 페이지의 내용을 가져오는 역할을 하지만, 네이버와 같은 웹 사이트는 웹 브라우저의 User-Agent 헤더에 대한 요구 사항을 가질 수 있습니다. 이러한 제한으로 인해 Java의 기본 URL 연결 방식만으로는 웹 페이지를 가져오지 못할 수 있습니다.
또한 네이버와 같은 웹 사이트는 HTTPS로 보안 연결을 사용하고 있기 때문에, SSL/TLS 인증서 관련 문제로 인해 웹 페이지를 가져오는 데 어려움이 있을 수 있습니다.
웹 페이지를 가져오기 위해 추가적인 설정이 필요하며, HTTPS 연결 및 User-Agent 설정 등을 고려해야 합니다. 그렇지 않을 경우 네트워크 관련 예외가 발생할 수 있습니다.
Java에서 웹 페이지를 가져오기 위해서는 HttpClient나 Jsoup과 같은 라이브러리를 사용하는 것이 더 편리하고 안정적일 수 있습니다. 이들 라이브러리는 HTTPS 연결 및 User-Agent 설정 등을 처리하기 쉽게 제공해 줄 수 있습니다.

SSL : 보안 소켓 계층(Secure Sockets Layer, SSL) 인증서는 종종 디지털 인증서로 불리며, 브라우저(사용자의 컴퓨터)와 서버(웹사이트) 사이의 암호화된 연결을 수립하는 데 사용됩니다.

TLS : TLS은 SSL의 향상된, 더욱 안전한 버전입니다. SSL이 더욱 일반적인 용어이기 때문에 DigiCert는 보안 인증서를 여전히 SSL로 언급하지만 DigiCert에서 SSL을 구입하면 가장 신뢰할 수 있는 최신 TLS 인증서를 얻을 수 있습니다.

2. 소켓 프로그래밍 

소켓 프로그래밍이란 소켓을 이용한 통신 프로그래밍을 뜻한다. 

소켓 : 프로세스간의 토신에 사용되는 양쪽 끝단을 의미한다.

java.net을 통해 자바에서 소켓 프로그래밍을 지원한다.

 

2.1 TCP와 UDP

TCP를 이용한 통신은 전화에, UDP를 이용한 통신은 소포에 비유된다.

TCP 순서

1. 먼저 상대방과 연결

2. 이후 데이터 전송 

    2.1 데이터 전송 실패시 재전송 

-> 파일 주고받을 때 적합

UDP 순서

1. 상대방과 연결하지 않고 데이터 전송

2. 데이터 수신 유무 확인x 

    2.1 전송 순서 바뀔수도 있음   

-> 게임이나 동영상의 데이터를 전송하는 경우 빠른 전송이 필요할 때 

 

2.2 TCP 소켓 프로그래밍

- 통신과정 

1. 서버 프로그램에서 서버소켓을 사용하여 서버 프로그램의 특정 포트에서 클라이언트 받을 준비 

2. 클라이언트 프로그램은 접속할 서버 IP주소와 포트 정보 가지고 소켓 생성해서 서버 요청

3. 서버프로그램은 클라이언트 연결 요청 받으면 새로운 소켓 생성해서 클라 소켓과 연결 

4. 둘이 일대일 통신 

 

서버 프로그램은 중간 통로 역할 해준다고 생각하면 된다. (전화교환기)

 

Socket : 프로세스간 통신 담당. InputStream과 OutputStream을 가지고 있음, 이 두  스트림을 통해 프로세스간의 통신이 이루어진다.

ServerSocket : 포트와 연결되어 외부 연결 요청 기다리다 요청이 들어오면, Socket을 생성해서 소켓과 소켓간의 통신이 이루어지도록 한다. 

 

Server

public class TcpIpServer {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try{
          serverSocket = new ServerSocket(7777);
          System.out.println(getTime() + "서버 준비 완료");

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        while(true){
            System.out.println(getTime() + "연결요청 기다림");
            try {
                Socket socket = serverSocket.accept();
                System.out.println(getTime() + socket.getInetAddress() +"로부터 연결요청이 들어왔습니다.");

                OutputStream out = socket.getOutputStream();
                DataOutputStream dos = new DataOutputStream(out);

                dos.writeUTF("[NOTICE] Test Message1 from Server.");
                System.out.println(getTime() + "데이터를 전송했습니다. ");

                dos.close();
                socket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }
    }

    static String getTime(){
        SimpleDateFormat f = new SimpleDateFormat("[hh:mm:ss]");
        return f.format(new Date());
    }
}

Client

public class TcpIpClient {
    public static void main(String[] args) {
        String serverIp = "127.0.0.1";
        System.out.println("서버에 연결중입니다. 서버IP : " + serverIp);
        try {
            Socket socket = new Socket(serverIp, 7777);

            InputStream in = socket.getInputStream();
            DataInputStream dis = new DataInputStream(in);

            System.out.println("서버로부터 받은 메시지 : " + dis.readUTF());
            System.out.println("연결을 종료합니다.");

            dis.close();
            socket.close();
            System.out.println("연결이 종료 됐습니다.");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

Server