---
title: "Java 정리 30"
date: "2018-12-24"
tags: ["Java"]
status: archived
verified: false
---

## Java 정리 30 - Network

---

### 네트워크

![01](/md/legacy-assets/java/30/01.webp)

* **컴퓨터끼리 정보를 주고 받기 위한 통신망**
  * 협의적 의미
  * 크기에 따라 LAN, MAN, WAN 
* **java.net 패키지**에서 관련 클래스를 제공
* 다른 컴퓨터와 정보를 주고 받기위해 생성하고 연결에 사용하는 객체들
  * **Socket, ServerSocket**
    * **TCP** 방식 구현할 때
  * **DatagramPacket, DatagramSocket**
    * **UDP** 방식 구현할 때
  * **InetAddress**
    * **접속자의 정보**를 얻을 때 
  * **URLEncoder, URLDecoder**
    * **문자열을 변환**할 때
* **위 클래스들은 연결만 수행, 데이터를 주고 받는 건 Stream**
* **허브**
  * 네트워크에 존재하는 여러가지 컴퓨터를 모으는 일을 함.
* **라우터**
  * 목적지 컴퓨터의 최단거리를 산출, 관리

![02](/md/legacy-assets/java/30/02.webp)

---

### OSI 7 Layer Model (Reference Model)

![03](/md/legacy-assets/java/30/03.webp)

* 실제로는 **TCP/IP Model**을 사용
* PD가 NT갔다가 SPA를 갔다(암기용)
* **Application(응용) 계층**
  * 사용자 Application
* **Presentation(표현) 계층**
  * 컴퓨터가 알아볼 수 있도록 반환
  * 암호화
* **Session(세션) 계층**
  * 가상 연결(호 단위 연결)
* **Transport(전송) 계층**
  * 실제 연결
  * TCP (Transmission Control Protocol)
  * UDP (User Datagram Protocol)
* **Network (네트워크) 계층**
  * 길찾기
* **Data Link (데이터링크) 계층**
  * MAC 물리계층으로 데이터 연결
* **Pysical (물리) 계층**
  * LAN선 사용 연결
    * RJ45 이용

---

### PDU (Protocol Data Unit) 

* 데이터 통신에서 상위 계층이 전달한 데이터에 붙이는 제어정보
* **header** - 계층을 식별하기 위한 이름이 붙는다.
* **body** - payload data를 가짐
* 데이터 계층이 내려갈때마다 pdu들이 다른 계층의 payload로 들어가면서 길어진다.(캡슐화)
* 다른 클라이언트가 받은 패킷은 header를 읽고 payload를 역순으로 데이터를 올려보냄

![04](/md/legacy-assets/java/30/04.webp)

---

### TCP, UDP

* **TCP (Transmission Control Protocol)**
* 전화에 비유
* **패킷의 크기가 고정**되어 있다.
  * **1packet = 8bit(1byte)**
* **신뢰성 통신 (오류 검출)**
  * **속도가 느리다.**
  * **오류검출하는 패킷이 존재**
  * 미전송 패킷을 다시 보낸다.
  * **중요한 데이터를 보낼 때 사용**(결제, 은행거래,..)
* **Socket, ServerSocket**

* **UDP(User Datagram Protocol)**
* 우편에 비유
* **패킷의 크기를 변경**할 수 있다.**(최대 512byte)**
* **비신뢰성 통신 (오류 검출 안함)**
  * **속도가 빠르다.**
  * **오류검출하는 패킷이 없음**
  * 반드시 데이터 전송되리란 보장이 없음
  * **중요하지 않은 데이터를 전달할 때 사용**(스트리밍, 화상전화, M2M(machine to machine)
* **DatagramSocket, DatagramPacket**

---

### 컴퓨터 환경의 변천사

* **중앙 집중식**
  * 한개의 서버가 존재, 여러 단말기가 붙은 형태
    * 예) 하이텔 단말기
    * 서버가 제공하는 데이터를 접목하여 사용
      * RAIDUS 과금형태
* **Client - Server** 
  * 서버가 존재하고 여러 클라이언트가 서버에 데이터를 요청하는 형태
  * 프로그램 배포에 문제
    * 문제 생기면 출장..
* **Web 환경**
  * 웹서버가 존재, 웹 클라이언트(웹브라우저)들이 데이터를 요청하는 형태
  * 웹서버로부터 화면을 받아 브라우저에서 그린다.
    * 브라우저마다 다르게 그려짐 -> 웹표준 탄생의 계기
  * 어디서나 접근가능(접근성)
* **RIA 환경**
  * **RIA(Rich Internet Application)**
    * **접속자의 자원을 더 많이 사용**
    * **AJAX(Asynchronous JavaScript and XML)**
  * **요즘 게임환경은 C/S환경과 Web환경이 합쳐진 형태**
    * Web환경으로 프로그램 배포한 후 웹 브라우저가 감당하기 힘들기 때문에 배포된 프로그램으로 C/S환경으로 게임서버와 게임 클라이언트간 통신
    * CS와 형태는 같음

---

### Network S/C 프로그래밍

**Server**
* 정보제공
* **ServerSocket 생성**
  * 통신 port 열림 : port 선점
  * 1024번 이하의 port는 이미 열려있는 port가 많다.

```java
// 주어진 포트번호로 서버소켓 생성, 접속자가 들어오길 기다림
ServerSocket ss = new ServerSocket(포트번호);
```

* **접속자 소켓을 받는다.**

```java
Socket client = ss.accept(); // blocking
```

**Client**
* 정보를 요청
  * 서버로부터 정보를 제공받는 애
* Socket 생성
  * 입력된 ip address와 port를 가지고 서버연결 시도

```java
Socket socket = new Socket(아이피주소,포트번호);
```

![05](/md/legacy-assets/java/30/05.webp)

```java
// SimpleServer
public class SimpleServer {
     public SimpleServer() throws IOException {
          
          // 1. PORT를 열고 접속자가 들어오기를  기다린다.
          ServerSocket server = null;
          try {
              server = new ServerSocket(3000);
              System.out.println("서버 가동중 "+server);
              // 3. 접속자가 들어오면 접속자 소켓을  받는다.
              Socket client = server.accept();
              System.out.println("접속자 있음 "+client);
          } finally {
              if (server!=null) server.close();
          }
     }
     
     public static void main(String[] args) {
          try {
              new SimpleServer();
          } catch (IOException e) {
              System.out.println("포트가 이미  사용중입니다.");
              e.printStackTrace();
          }
     }
}
```

```java
// SimpleClient
public class SimpleClient {
     
     public SimpleClient() throws UnknownHostException,  IOException {
          // 2. 소켓을 생성 : 내 컴퓨터에 들어갈 때는  localhost 또는 127.0.0.1(루프백)
          // 다른 컴퓨터에 들어갈 때에는 ip address
          Socket client = new  Socket("localhost",3000);
          System.out.println("서버에 접속 하였습니다.  "+client);
     }
     
     public static void main(String[] args) {
          try {
              new SimpleClient();
          } catch (UnknownHostException e) {
              e.printStackTrace();
          } catch (IOException e) {
              e.printStackTrace();
          }
     }
}
```

![06](/md/legacy-assets/java/30/06.webp)

* 방화벽 설정이 안돼 있으면 외부와 통신이 안될 수 있음
  * 제어판에서 인바운드, 아웃바운드 규칙을 추가해 주어 해결


---

### 데이터 전송하기

* TCP는 패킷이 고정길이 1packet = 8bit(1byte)

**Server** 
* 접속자 소켓을 받은 후 문자열 쓰기
* **DataOutputStream 사용**
	* Java의 데이터형을 스트림으로 내보낼 때 사용하는 Stream

```java
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
```

![07](/md/legacy-assets/java/30/07.webp)


* **쓰기**
  * **입력된 문자열이 %로 분할(인코딩)되어 스트림에 기록**
  * **flush**로 스트림에서 분출

```java
dos.writeUTF("문자열");
dos.flush();
```

**Client**
* 보내온 문자열을 읽기 위한 스트림을 사용

```java
DataInputStream dis = new DataInputStream(socket.getInputStream())
```

![09](/md/legacy-assets/java/30/09.webp)


* **읽기**
  * 인코딩된 한글을 원래대로 조립하여 보여준다.

```java
dis.readUTF();
```

![08](/md/legacy-assets/java/30/08.webp)

```java
// 위와 동일한 SimpleServer 예제
public SimpleServer() throws IOException {
    
    // 1. PORT를 열고 접속자가 들어오기를  기다린다.
    ServerSocket server = null;
    // 접속자에게 보내줄 메시지
    String msg = "☆ ˚ * ˚★\n" +
              " ▲  △  ▲  \n" +
              "(^^)('')('')\n" +
              "▶◀▶◀▶◀\n" +
              "메리크리스마스\n" +
              "해피뉴이어~ -오영근-";
    // 접속자에게 메시지를 보내기 위한 스트림을  선언
    DataOutputStream dos = null;
    try {
        server = new ServerSocket(3000);
        System.out.println("서버 가동중 "+server);
        while(true) { // 계속 실행
              // 3. 접속자가 들어오면 접속자 소켓을  받는다.
              Socket client = server.accept();
              System.out.println("접속자 있음  "+client);
              
              // 접속자에게 메시지를 보내기 위한  연결
              dos = new  DataOutputStream(client.getOutputStream());
              // 얻어낸 스트림에 데이터 쓰기
              dos.writeUTF(msg);
              // 스트림의 데이터를 목적지(소켓)로  분출
              dos.flush();
        }
        
    } finally {
        if (server != null) server.close();
        if (dos != null) dos.close();
    }
}
```

```java
public SimpleClient() throws UnknownHostException,  IOException {
  // 2. 소켓을 생성 : 내 컴퓨터에 들어갈 때는  localhost 또는 127.0.0.1(루프백)
  // 다른 컴퓨터에 들어갈 때에는 ip address
  Socket client = null;
  // 서버에서 보내오는 메시지를 읽기위한 스트림
  DataInputStream dis = null;
  try {
      String ip = JOptionPane.showInputDialog(""
                + "서버  ip\n130,132.133.134,135,157,146"
                +  ",131,141,142,143,144,155,146,148,149,151,152,153");
      client = new Socket("000.00.00."+ip,3000);
      System.out.println("서버에 접속  하였습니다. "+client);
      // 소켓에서 스트림 얻기
      dis = new  DataInputStream(client.getInputStream());
      
      // 서버에서 보내온 메시지 읽기
      String revMsg = dis.readUTF();
      JOptionPane.showMessageDialog(null,  "서버의 메시지 : "+revMsg);
  } finally {
      if(client != null) client.close();
      if(dis != null) dis.close();
  }
}
```

![10](/md/legacy-assets/java/30/10.webp)
