본문 바로가기

플밍 is 뭔들/JAVA

[자바] 네트워킹 (Networking)

※ 네트워킹이란?
두 대 이상의 컴퓨터를 케이블로 연결하여 네트워크를 구성하는 것.
컴퓨터들을 서로 연결하여 데이터를 손쉽게 주고받거나 또는 자원(프린터와 같은 주변기기)을 함께 공유하고자 하는 노력에서 시작됨.
자바에서 제공하는 java.net 패키지를 사용하면 네트워크 어플리케이션의 데이터 통신 부분을 쉽게 작성할 수 있으며, 간단한 네트워크 어플리케이션은 단 몇 줄의 자바코드 만으로도 작성이 가능.


※ 클라이언트/서버 (client/server)
클라이언트 : 서비스를 사용하는 컴퓨터
서버 : 서비스를 제공하는 컴퓨터


※ 서비스
서버가 클라이언트로부터 요청받은 작업을 처리하여 그 결과를 제공하는 것.
ex) 파일 서버, 메일 서버, 어플리케이션 서버 등등


※ 서버기반 모델 / p2p 모델
서버기반 모델 : 전용서버를 두고 네트워크를 구성
p2p 모델 : 클라이언트가 서버의 역할까지 동시에 수행하여 네트워크를 구성
서버기반 모델(server-based-model)
p2p 모델(peer-to-peer-model)
- 안정적인 서비스 제공이 가능하다.
- 공유 데이터의 관리와 보안이 용이하다.
- 서버구축비용과 관리비용이 든다.
- FTP 서버프로그램이나 Tomcat과 같은 
  웹서버 프로그램을 설치하면 일반 PC도 
  서버의 역할이 가능하다.
- 서버구축 및 운용비용 절감
- 자원의 활용을 극대화 할 수 있다.
- 자원의 관리가 어렵다.
- 보안이 취약하다.
- 예로는 토렌트가 있다.


※ IP주
컴퓨터를 구별하는데 사용되는 고유한 값으로 인터넷에 연결된 모든 컴퓨터는 IP주소를 갖는다.
4byte (32bit)의 정수로 구성되어 있으며 1byte당 0~255사이의 정수로 구성되어 있다.


※ InetAddress
자바에서 IP 주소를 다루기 위한 클래스

사용 예시
public class Main {
      
      public static void main(String[] args){
            
            InetAddress ip = null;
            InetAddress[] ipArr = null;
            
            try {
                  ip = InetAddress.getByName("debugdaldal.tistory.com");
                  System.out.println("getHostName() : " + ip.getHostName());
                  System.out.println("getHostAddress() : " + ip.getHostAddress());
                  System.out.println("toString() : " + ip.toString() );
                  
                  byte[] ipAddr = ip.getAddress();
                  System.out.println("getAddress() : " + Arrays.toString(ipAddr));
                  
                  String result ="";
                  for(int i =0; i< ipAddr.length; i ++){
                        result += (ipAddr[i]<0) ? ipAddr[i] + 256 : ipAddr[i];
                        result += ".";
                  }
                  
                  System.out.println("getAddress() + 256 : " + result);
                  System.out.println();
                  
            } catch (UnknownHostException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }
            
            try {
                  ip = InetAddress.getLocalHost();
                  System.out.println("getHostName() : " + ip.getHostName());
                  System.out.println("getHostAddress() : " + ip.getHostAddress());
                  System.out.println("toString() : " + ip.toString() );
                  
            }catch (UnknownHostException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }
            
            try {
                  ipArr = InetAddress.getAllByName("debugdaldal.tistory.com");
                  
                  for(int i = 0; i< ipArr.length; i++){
                        System.out.println("ipArr[" + i +"] : " + ipArr[i]);
                  }
            } catch (UnknownHostException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }
      }
}

결과
getHostName() : debugdaldal.tistory.com
getHostAddress() : 175.126.170.110
getAddress() : [-81, 126, -86, 110]
getAddress() + 256 : 175.126.170.110.
getHostName() : taehee
getHostAddress() : 나의 IP주소가 출력됨
toString() : taehee/나의 IP주소가 출력됨

하나의 도메인명(debugdaldal.tistory.com)에 여러 IP주소가 매핑될 수 있기 때문에 getAllByName()를 통해 모든 IP 주소를 알 수 있다. 또한 getLocalHost()를 통해 내 PC의 IP주소와 호스트명을 알 수 있다.


※ URL (Uniform Resource Location)
인터넷에 존재하는 여러 서버들이 제공하는 자원에 접근할 수 있는 주소를 표현한 것
'프로토콜://호트트명:포트번호/경로명/파일명?쿼리스트링#참조' 의 형태로 이루어져 있다. (포트번호, 쿼리, 참조는 생략가능) 

프로토콜 : 자원에 접근하기 위해 서버와 통신하는데 사용되는 통신규약 (http)
호스트명 : 자원을 제공하는 서버의 이름 (debugdaldal.tistory.com)
포트번호 : 통신에 사용되는 서버의 포트번호
경로명 : 접근하려는 자원이 저장된 서버상의 위치
파일명 : 접근하려는 자원의 이름
쿼리(query) : URL에서 '?' 이후의 부분 
참조(anchor) : URL에서 '#' 이후의 부분

사용예시
try {
                  
                  //url 객체 생성... url 객체 생성자는 다양하니 상황에 맞게 사용
                  URL url = new URL("http://debugdaldal.tistory.com/170";);
                  //호스트명과 포트 출력
                  System.out.println("url.getAuthority() : " + url.getAuthority());
                  //url의 기본포트 반환(http 또는 80)
                  System.out.println("url.getDefaultPort() : " + url.getDefaultPort());
                  //포트반환
                  System.out.println("url.getPort() : " + url.getPort());
                  //파일명 반환
                  System.out.println("url.getFile() : " + url.getFile());
                  //호스트명 반환
                  System.out.println("url.getHost() : " + url.getHost());
                  //경로명 반환
                  System.out.println("url.getPath() : " + url.getPath());
                  //프로토콜 반환
                  System.out.println("url.getProtocol() : " + url.getProtocol());
                  //쿼리반환
                  System.out.println("url.getQuery() : " + url.getQuery());
                  //참조반환
                  System.out.println("url.getRef() : " + url.getRef());
                  //사용자정보 반환
                  System.out.println("url.getUserInfo() : " + url.getUserInfo());
                  //url을 문자열로 반환
                  System.out.println("url.toExternalForm() : " + url.toExternalForm());
                  //url uri로 변환
                  System.out.println("url.toURI() : " + url.toURI());
                  
            } catch(Exception e){
                  e.printStackTrace();
            }


※ URLConnection
어플리케이션과 URL간의 통신연결을 나타내는 클래스의 최상위 클래스로 추상위 클래스이다.
URLConnection을 상속받아 구현한 클래스로는 HttpURLConnection과 JarURLConnection이다. 
URLConnection을 이용하여 연결하고자 하는 자원에 접근하고 읽고 쓰기를 할 수 있다.
그 외에 관련된 정보를 읽고 쓸 수 있는 메서드가 제공된다. 
이 클래스는 제공되는 메서드가 많기 때문에 필요할 때 직접 적절한 메서드를 찾아서 사용해보자.


※ 소켓 프로그래밍
소켓을 이용한 통신 프로그래밍을 뜻한다.
소켓(socket)이란 프로세스간의 통신에 사용되는 양쪽 끝단(endpoint)을 의미한다.
서로 멀리 떨어진 두 사람이 통신하기 위하여 전화기가 필요한 것처럼, 프로세스간의 통신을 위해서는 그 무언가가 필요하고 그것이 바로 소켓이다.
자바는 java.net패키지를 통해 소켓 프로그래밍을 지원하는데, 소켓통신에 사용되는 프로토콜에 따라 다른 종류의 소켓을 구현하여 제공한다.


※ TCP와 UDP
TCP/IP 프로토콜은 이기종 시스템간의 통신을 위한 표준 프로토콜로 프로토콜의 집합이다.
TCP와 UDP 모두 TCP/IP 프로토콜에 포함되어 있으며 OSI 7계층의 전송계층(transport layer)에 해당하는 프로토콜이다.
TCP와 UDP는 전송 방식이 다르며, 각 방식에 따른 장단점이 있다. 어플리케이션의 특징에 따라 적절한 프로토콜을 선택하여 사용하도록 하자.
TCP
UDP
연결방식
연결기반
- 연결 후 통신(전화기)
- 1:1 통신방식
비연결기반
- 연결없이 통신(소포)
- 1:1, 1:n, n:n 통신방식 
특징
데이터의 경계를 구분안함
신뢰성 있는 데이터 전송
- 데이터의 전송순서가 보장됨
- 데이터의 수신여부를 확인함
  (데이터가 손실되면 재전송함)
- 패킷을 관리할 필요가 없음
UDP보다 전송속도가 느림
데이터의 경계를 구분함
신뢰성 없는 데이터 전송
- 데이터의 전송순서가 바뀔 수 있음
- 데이터의 수신여부를 확인안함
  (데이터가 손실되어도 알 수 없음)
- 패킷을 관리해주어야 함
TCP보다 전송속도가 빠름
관련 클래스
Socket
ServerSocket
DatagramSocket
DatagramPacket
MulticastSocket
TCP는 데이터 전송 전 상대방과 연결이 됐는지 확인한 후 데이터를 전송한다. 그리고 전송이 잘 되었는지 확인하고 전송에 실패했다면 해당 데이터를 재전송하기 때문에 신뢰있는 데이터의 전송이 요구되는 통신에 적합하다.
ex) 파일전송

UDP는 상대편과 연결하지 않고 데이터를 전송하며, 데이터를 전송하지만 바르게 수신되었는지는 확인하지 않기 때문에 데이터가 전송되었는지 확인할 길이 없다. 또한 데이터를 보낸 순서로 수신한다는 보장이 없다. 대신 이러한 확인 과정이 없기 때문에 TCP에 비해 전송 속도가 빠르다.
ex) 게임이나 동영상 데이터를 전송하는 경우 (이때 전송 순서가 바뀌어 늦게 도착한 데이터는 무시하면 된다.)


※ TCP소켓
서버와 클라이언트간의 1:1통신이므로 먼저 서버 프로그램이 실행되어 클라이언트 프로그램의 연결요청을 기다려야한다.

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

즉 일대일 연결을 하는 소켓 두개(서버에서 새로 생성된 소켓 하나 와 클라이언트 소켓 하나)와 서버 소켓 총 3개가 필요하다.
서버 소켓은 전화교환기, 일대일 연결되는 소켓은 전화기로 보면 된다.


※ UDP소켓
TCP는 ServerSocket과 Socket을 사용하지만 UDP는 DatagramSocket과 DatagramPacket을 사용한다.
UDP는 연결지향적인 프로토콜이 아니기 때문에 ServerSoket이 필요하지 않다. 
UDP통신에 사용하는 소켓은 DatagramSocket이며 데이터를 DatagramPacket에 담아서 전송한다.