Java/Java의 정석

Chapter 16 네트워킹(Networking)

계란💕 2023. 3. 2. 02:59

1. 네트워킹(Networking)

  • 네트워킹(Networking): 두 대 이상의 컴퓨터를 케이블로 연결해서 네트워크를 구성하는 것을 말한다. 
  • 초기의 네트워크는 몇 대의 컴퓨터로 구성됐으나 현재는 셀 수 없을 정도로 많은 컴퓨터가 인터넷이라는 하나의 거대한 네트워크를 구성하고 있으며 인터넷을 통해 다양하고 방대한 양의 데이터를 공유 가능하다. 
  • 자바의 java.net 패키지를 이용하면 네트워크 애플리케이션의 데이터 통신 부분을 쉽게 작성 가능

1.1 클라이언트(client)와 서버(server)

  • 클라이언트와 서버는 컴퓨터간의 관계를 역할로 구분하는 개념이다. 
  • 서버(server): 서비스를 제공하는 컴퓨터
    • 보통적으로 서버는 다수의 클라이언트에게 서비스를 제공하기 때문에 고사양의 하드웨어를 갖춘 컴퓨터이다. 
    • 서비스: 서버가 클라이언트로부터 요청 받은 작업을 처리하고 그 결과를 제공하는 것을 말한다. 
    • 파일 서버(file server): 클라이언트가 요청한 파일은 제공하는 서비스를 수행한다. 
    • 메일 서버(mail server): 
    • 어플리케이션 서버(application server)
    • 일반 PC는 주로 클라이언트 역할이지만, FTP Serv-U 같은 FTP 서버프로그램이나 Tomcat 같은 웹 서버 프로그램을 설치하면 서버 역할을 수행할 수 있다. 
  • 클라이언트(client): 서비스를 사용하는 컴퓨터
  • P2P(peer to peer) 모델: 별도의 전용 서버 없이 각 클라이언트가 서버 역할을 동시에 수행하는 모델이다.
    • 소리바다, 푸르나 같은 파일 공유 프로그램은 클라이언트 프로그램, 서버프로그램을 하나로 합친 것이다. 
    • 이를 설치한 컴퓨터는 클라이언트인 동시에 서버가 되므로 회원끼리 서로 파일을 주고 받을 수 있다.

서버 기반 모델과 P2P 모델의 차이점

  • 서버 기반 모델(Server based model): 네트워크를 구축할 때 전용 서버를 두는 모델
    • 안정적 서비스 제공
    • 공유 데이터의 관리와 보안이 용이하다.
    • 서버 구축 비용과 관리 비용이 든다. 
  • P2P(peer to peer)  모델: 별도의 전용 서버 없이 각 클라이언트 서버 역할을 동시에 수행하는 모델이다.  
    • 서버 구축, 관리 비용 절감
    • 자원 활용을 극대화
    • 보안 취약하다. 
    • 자원 관리가 어려움

1.2 IP 주소(IP address)

  • IP 주소는 컴퓨터(host, 호스트)를 구별하는데 사용되는 고유한 값으로 인터넷에 연결된 모든 컴퓨터는 IP 주소를 갖는다. 
  • 4 byte(32 bit)의 정수로 구성된다. 
  • IP 주소는 호스트 주소(24bit)와 네트워크 주소(8bit)로 구성된다. 
    • 호스트 주소가 0이면 자신을 나타낸다. 
  • 서로 다른 두 호스트의 IP 주소의 네트워크 주소가 같은 경우는 두 호스트가 같은 네트워크에 포함됐다는 뜻이다. 
    • 예를 들어, 하나의 무선 공유기로 여러 대의 스마트폰, 노트북을 연결하고 IP 주소를 조회하면 같은 IP 주소가 나온다. 
  • IP 주소 서브넷 마스크(Subnet Mask)를 비트연산자로 '&' 연산하면 IP 주소에서 네트워크 주소만을 뽑아낼 수 있다. 

1.3 InetAddress

  • Java에서는 IP 주소를 다루기 위한 클래스로 InetAddress 를 제공한다. 
  • 하나의 도메인명(ex. www.naver.com)에 여러 IP 주소가 매핑될 수도 있고 그 반대의 경우도 가능하기 때문에 전자의 경우는 getAllByName()을 통해 모든 IP 주소를 얻을 수 있다. 
  • getLocalHost()를 사용하면 호스트명IP 주소를 알아낼 수 있다. 

 


1.4 URL (Uniform Resource Locator)

  • Def) URL(Uniform Resource Locator)는 인터넷에 존재하는 여러 자원에 접근 가능한 주소를 표현하기 위한 것이다. 
  • ex) http://www.codechobo.com:80/sample/hello.html?referer=codechobo#index1
    • 프로토콜: 자원에 접근하기 위해 서버와 통신하는데 사용하는 규약(http)
    • 호스트명: 자원을 제공하는 서버의 이름 (www.codechobo.com)
    • 포트번호: 통신에 사용되는 서버의 포트 번호(80)  http 프로토콜에서는 80번 포트를 사용한다. 이를 생략하면 80번으로 간주한다. 
    • 경로명: 접근하려는 자원이 저장된 서버상의 위치(/sample/)
    • 파일명: 접근하려는 자원의 이름 (hello.html)
    • 쿼리(query): URL에서 '?' 이후의 부분 (referer=codechobo)
    • 참조(anchor): URL에서 '#' 이후의 부분(index1)

1.5 URLConnection

  • URLConnection은 애플리케이션과 URL간의 통신 연결을 나타내는 클래스의 최상위 클래스로 추상 클래스이다. 
  • 하위 클래스로 HttpURLConnection, JarURLConnection이 있다. 

 

 


2. 소켓 프로그래밍

  • Def) 소켓 프로그래밍은 소켓을 이용한 통신 프로그래밍을 뜻한다. 
    • Def) 소켓(socket): 프로세스 간의 통신에 사용되는 양쪽 끝단(endpoint)을 의미한다. 
  • java.net 패키지를 통해서 소켓 프로그래밍을 지원한다. 
    • 소켓 통신에 사용되는 프로토콜에 따라서 다른 종류의 소켓을 구현해서 제공한다. 

2.1 TCP(Transfer Control Protocol)와 UDP(User Datagram Protocol)

  • TCP/IP 프로토콜은 이기종 시스템간의 통신을 위한 표준 프로토콜로 프로토콜의 집합이다. 
  • OSI 계층의 전송 계층(transfer layer)에 해당한다. 
  • 어플리케이션의 특성에 따라 선택해서 사용한다. 
항목 TCP UDP
연결 방식
연결 기반(connection-oriented)
 - 연결 후 통신(전화기)
 -  1:1 통신 방식
비연결 기반(connectionless-oriented)
 - 연결 없이 통신
 - 1:1, 1:n, n:n 통신 방식
특징 데이터의 경계를 구분하지 않는다. 
신뢰성있는 데이터 전송
 - 데이터 전송 순서 보장
 - 데이터의 수신 여부를 확인
   -> 손실 시, 재전송
 - 패킷 관리할 필요 없다. 
 - UDP 보다 느림

Ex) 파일 전송

데이터의 경계를 구분한다. (Datagram)
신뢰성 없는 데이터 전송
 - 데이터의 전송 순서가 바뀔 수 있다. 
 -  데이터의 수신 여부를 확인하지 않는다. 
   -> 데이터 손실 여부 알 수 없음
 - 패킷관리해줘야한다. 
 - TCP보다 빠름 (수신 여부를 확인하지 않아서)

  Ex) 동영상 스트리밍

관련 클래스 Socket
ServletSocket
DatagramSocket
DatagramPacket
MultocastSocket

 


2.2 TCP 소켓 프로그래밍

  • TCP 소켓 프로그래밍은 클라이언트와 서버 간의 일대일 통신이다. 
  • 서버소켓(ServerSocket) 은 포트와 결합되어 포트를 통해서 원격 사용자의 연결 요청을 기다리다가 요청이 올 때마다 새로운 소켓을 생성해서 상대편 소켓과 통신할 수 있도록 연결한다. 
    • 서버 소켓은 연결만 처리한다. 
  • 실제적인 데이터 통신은 서버소켓과  관계없이 소켓과 소켓 간에 이뤄진다. 
    • 소켓들이 데이터를 주고받는 연결 통로는 바로 입출력스트림이다.  
  • 서버소켓은 전화 교환기, 소켓은 전화기에 비유 가능
  • 서버소켓은 포트를 독점한다. 반면에, 소켓은 하나의 포트 번호를 공유해서 사용 가능하다. 
  • 포트는 호스트가 외부와 통신을 하기 위한 통로로 하나의 호스트가 65536(포트 번호는 0~65535에 속하는 값이다.)개의 포트를 가지고 있다. 
  • 보통 1023번 이하의 포트는 다른 프로그램에 의해 사용되는 경우가 많으니 1023 이상의 번호 중에서 사용하지 않느 번호를 사용해야한다. 

 

출처 - https://m.blog.naver.com/kkkths/221872002827

  • 소켓은 위와 같이 두 개의 스트림(InputStream, OutputStream)을 가지고 있다.
  • 스트림들은 반대편 소켓의 스트림들과 교차 연결된다. 

 


Java 소켓 관련 클래스

  • Socket: 프로세스간의 통신을 담당하며 InputStream, OutputStream을 가지고 있다. 두 스트림을 통해서 프로세스간의 통신(입출력)이 이뤄진다.
  • ServletSocket: 포크와 연결되서 외부의 연결 요청이 들어오면 socket을 생성해서 소켓 간 통신이 이뤄지도록 한다. 한 포트에 한 ServerSocket만 연결 가능하다. 
    • 프로토콜이 다르면 같은 포트를 공유가능하다. 

 


서버 프로그램과 클라이언트 프로그램의 통신 과정

  1. 서버 프로그램에서는 서버소켓을 사용해서 서버 컴퓨터의 특정 포트에서 클라이언트의 연결 요청을 처리할 준비를 한다. 
  2. 클라이언트 프로그램은 접속할 서버의 IP 주소포트 정보를 가지고 소켓을 생성해서 서버에 연결을 요청한다. 
  3. 서버소켓은 클라이언트의 연결 요청을 받으면 서버에 새로운 소켓을 생성해서 클라이언트의 소켓과 연결되도록 한다. 
  4. 이제 클라이언트의 소켓과 새로 생성된 서버의 소켓은 서버 소켓과 관계 없이 일대일 통신을 한다. 

 Ex) TCP

 


2.3 UDP 소켓 프로그래밍

  • TCP 소켓 프로그래밍에서는 Socket과  ServerSocket을 사용하지만 UDP소켓 프로그래밍에서는 DatagramSocketDatagramPacket을 사용한다. 
  • UDP는 연결 지향이 아니므로 ServerSocket가 필요없다. 
  • UDP 통신에서 DatagramSocket를 사용하고 데이터를 DatagramPacket에 담아서 전송한다. 
    • DatagramPacket: 헤더(패킷을 수신한 호스트의 정보) + 데이터
    • 패킷을 전송하면 DatagramPacket에 지정된 주소의 DatagramSocket에 도착한다. 

  Ex)  UdpClient

  • 주의: UdpServer를 먼저 실행한다음에 UdpClient를 실행한다. 
<hide/>
public class UdpClient {

    public void start() throws IOException, UnknownHostException {

        DatagramSocket datagramSocket = new DatagramSocket();
        InetAddress serverAddress = InetAddress.getByName("127.0.0.1");

        // 데이터가 저장된 공간으로  byte 배열을 생성한다. 
        byte[] msg = new byte[100];
        DatagramPacket outPacket = new DatagramPacket(msg, 1, serverAddress, 7777);
        DatagramPacket inPacket = new DatagramPacket(msg, msg.length);

        datagramSocket.send(outPacket);
        datagramSocket.receive(inPacket);

        System.out.println("current server time : " + new String(inPacket.getData()));
        datagramSocket.close();
    }

    public static void main(String[] args) {

        try {
            new UdpClient().start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

  Note) 실행 결과

  • 다음과 같이 터미널에서 실행해준다.

 

 

 

  Ex)  UdpServer

<hide/>
public class UdpServer {

    public void start() throws IOException, BindException {

        // Port 7777번을 사용하는 소켓을 생성한다.
        DatagramSocket socket = new DatagramSocket(7777);
        DatagramPacket inPacket, outPacket;

        byte[] inMsg = new byte[10];
        byte[] outMsg;

        while (true) {

            // 데이터를 수신하기 위한 패킷을 생성한다.
            inPacket = new DatagramPacket(inMsg, inMsg.length);

            // 패킷을 통해 데이터를 수신한다.
            socket.receive(inPacket);

            // 수신한 패킷으로부터 client 의 IP 주소, port 번호를얻는다.
            InetAddress address = inPacket.getAddress();
            int port = inPacket.getPort();

            // 서버의 현재 시간을 출력
            SimpleDateFormat sdf = new SimpleDateFormat("[hh:mm:ss]");
            String time = sdf.format(new Date());
            outMsg = time.getBytes();   // 서버의 시간을 byte 배열로 변환한다.

            // 패킷을 생성해서 클라이언트에게 패킷 전송
            outPacket = new DatagramPacket(outMsg, outMsg.length, address, port);
            socket.send(outPacket);
        }
    }

    public static void main(String[] args) {
        try {
            new UdpServer().start();        // UDP 서버를 실행
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

  • 오류: java.net.BindException

  • 원인 : 해당 포트가 이미 사용중일 때 발생하는 예외이다.
  • 해결
    • cmd 창에서 다음 명령어로 내가 사용하고 있는 port 번호와  PID를 확인한다. 
    • 현재 UdpServer 클래스에서 7777번 포트를 쓰고 있으니까 PID 번호를 이용해서 kill 하면 된다.
    • taskkill /f /pid  (PID번호)    입력하고 나면 다음과 같이 프로세스가 종료되었다고 나온다. 

  Note) 실행 결과

  • 서버로부터 서버 시간을 전송 받아서 출력하는 UDP 클라이언트와 서버 프로그램이다. 
  • 클라이언트가 DatagramPacket을 생성해서 DatagramSocket으로  서버에 전송하면 서버는 전송 받은 DatagramPacket의 getAddress(), getPort()를 호출해서 클라이언트의 정보를 얻어서 서버시간을 패킷에 담아 전송


모르는 부분 및 기타

  • FTP(File Transfer Protocol, 파일 전송 프로토콜): TCP/IP 프로토콜을 가지고 서버와 클라이언트 사이의 파일 전송을 위한 프로토콜이다. TCP/IP 프로토콜 테이블의 응용 계층에 속한다. 
  • Telnet(텔넷, tel 통신 + net 네트워크): 사용자의 컴퓨터에서 네트워크를 이용해서 원격지에 떨어진 서버에 접속해서 자료를 교환할 수 있는 프로토콜을 말한다. 자신의 컴퓨터처럼 사용 가능하다.  
    • 요즘은 보안상 문제(데이터가 암호화되지 않는다.) 때문에 SSH를 많이 사용한다. 
    • 주요 네트워크 프로토콜 중 하나이다. 
    • 포트번호 23번
  • SSH(Secure SHell, 시큐어 셸): 네트워크 상의 다른 컴퓨터에 로그인하거나 원격 시스템에서 명령을 실행하고 다른 시스템으로 파일을 복사할 수 있도록 해주는 응용 프로그램 또는 프로토콜을 말한다. 
    • Telnet과 SSH는 기능이 비슷하다. 
    •  암호화 통신을 하기 때문에 비교적 안전하다. 
    • 포트번호 22번
  • 서브넷 마스크(Subnet Mask): 서브넷을 구분하는 방법 중 하나이다.
  • 네트워크 패킷(Network packet, 패킷): 컴퓨터 네트워크가 전달하는 데이터의 형식화된 블록이다. 
    • 제어 정보와 사용자 데이터로 이뤄진다. 
    • 데이터의 전송 단위이다. 
  • PID(Process ID, 프로세스 식별자): OS에서 프로세스를 식별하기 위해 부여하는 번호이다.

 

출처 - 「Java의 정석 - 남궁성」

참고 링크)

https://qpar.tistory.com/13