2018년 10월 29일 월요일

Network 중간정리,

지금까지 살펴본 네트워크에 대해서 중간정리를 해보자.


1. OSI7계층
: 서로다른 단말기간의 데이터를 네트워크 상에서 송/수신 하기위해 표준화된 통신 규약에 해당하는 각 영역별로 정리된 계층이다.

 ↓ 아래로 갈 수록 하위 계층
 7) Application Layer
 6) Presentation Layer
 5) Session Layer
 4) Transport Layer
 3) Network Layer
 2) DataLink Layer                                       
 1) Physical Layer           

위에 설명된 것들이 해당 영역의 계층들이며, 데이터가 송신될때, 해당 데이터 패킷이 각계층을 거쳐 캡슐화 된 후 네트워크를 통해 전달되어 분리되서 다시 해당 계층을 역순으로 데이터가 전송된다.

위의 OSI7계층을 다음과 같이 4계층으로 표현하기도한다.
 4) Application (OSI 7계층의 Application / Presentation / Session Layer가 해당됨.)
 : 사용자와 가장 인접한 계층이며, 네트워크를 응용프로그램(Telnet, FTP, SMTP)으로 이용한다.

 3) Transport (OSI 7계층의 Transport Layer가 해당됨.)
 : 데이터를 전송하는 역할을 담당한다. 각 시스템을 연결하여 TCP프로토콜을 사용해서 데이터를 전송한다.

 2) Internet (OSI 7계층의 Network Layer가 해당됨.)
 : 데이터를 올바른 목적지까지 전송하기 위해 패킷들을 경로를 지정한다.
IP프로토콜을 사용해서 라우팅을 역할을 한다.

 1) Network Interface (OSI 7계층의 DataLink / Physical Layer가 해당됨.)
 : 이더넷 카드 같은 하드웨어 장치를 뜻한다. 두 단말기간에 데이터를 어떤형태로 주고 받을지 데이터 전송방식을 정한다.  (아날로그신호 → 디지털신호로 / 디지털신호 → 아날로그)




2. ICMP
 Network Layer에 해당하는 프로토콜이며, ICMP헤더를 통해서 패킷들의 정보를 파악할 수 있다.

 - 고정된 4byte + 가변길이 4byte를 갖고있다.

 - 헤더 형태
  • Type (8bit)
  • Code (8bit)
  • CheckSum (16bit)
  • 가변 길이 (32bit)
  • Type : 메시지 유형을 정의한다. 보통 ping의 Echo사용시 - 메시지 유형 8번에 해당 됨.(패킷이 도달하지 못했을 경우 3으로 표시)
  • Code : Type에 대한 부가적인 설명을 한다. 이상이 없을 경우 보통 0번에 해당하는 값을 표시.
  • CheckSum : ICMP헤더의 패킷 손상여부를 체크. (네트워크를 통해 전송된 패킷이 변경여부(무결성)를 파악 할 수 있다.)
- CheckSum 방법
 1) ICMP헤더 패킷을 2바이트씩 16비트워드로 표현한다.
 2) 해당 값들을 전부 다 더한다. (기존 checksum에 해당하는 값들에 대해서는 0만들어서 계산하거나 무시하고 계산해야한다.) 이때, 캐리가 발생하였다면 더해주면된다.
 3) 해당 값들을 1의 보수로 표현하고 16진수로 바꿔준 뒤 기존의 CheckSum값과 비교하기. 기존 CheckSum값과 같을경우 패킷의 무결성을 인증한다.




3. RFC

 - Time Protocol
 : 각 독립된 사이트를 컴퓨터로 읽을 수 있는 날짜와 시간을 제공해준다.
   (1900년 1월 자정 이래로 초 단위로 시간을 보낸다.)

 - Daytime Protocol
 : 이 서비스는 입력된 값에 관계없이 현재 날짜와 시간을 문자열로 보내준다.





4. Encoding 

 - Encoding
(Encoding)인코딩은 문자를 컴퓨터로 저장하거나 불러오기 위해서 컴퓨터가 이해할 수 있도록 문자를 바이트로 표현하는 방법이다.
보통 컴퓨터에 사람이 사용하는 언어의 데이터로 저장하기 위해서 사용됨.

 - Encoding Type
  • ASCII : 영문/숫자/기호로 이루어진 영문키보드에 해당된 모든 값들을 1바이트로 표현한다. 0~127개 즉, 128개의 부호로 표현하며, 2byte이상의 값들은 표현할 수 없다.
  • Unicode : 전 세계의 문자를 2byte로 표현하며, 문자, 숫자가 각각 1:1매핑이 되어있다.
  • UTF-8 : ANSI(영어포함)문자를 1byte, 아시아 문자(한글 / 한문)는 3byte로 가변표기하는 방식이다.
  • MS-949 : 한글확장 완성형 방식이다. euc-kr이 표현할 수 없는 똠방각하를 표현할 수 있다.

5. Thread

 - Thread
 하나의 프로세스내에서 프로그램을 실행하는 작업 단위이다. 해당 프로세스 내에서 동작을 독립적으로 수행할 수 있다.

예를들어, 하나의 프로그램에 2개 이상의 작업을 수행할때, 기존에는 하나의 작업이 완료된 직후 다음작업을 실행하였다면, 쓰레드를 사용한다면, 하나의 작업을 하는동안에 다른작업도 같이 독립적으로 수행할 수 있는것이다.

하지만, Thread는 꼭 독립적인 작업을 할 필요는 없다.

 - synchronized (동기화)
 예를들어 A(), B(), C()의 작업 3가지가 존재할경우, A()와 B()는 각각 동시에 수행해도 되는 작업이며, C()의 작업은 동시에 접근할 수 없도록 하기위해서 synchronized를 이용한다.
그러면 1번 이라는 쓰레드가 C()에 접근하고 있는 상태면, 다른 쓰레드들은 1번 쓰레드가 종료될 때 까지 접근할 수 없고 기다려야 한다.

 - wait()
 wait은 작업중인 쓰레드에 대해서 대기상태로 만들어버린다. 즉 누군가 깨워야만 작업이 진행된다. notify()를 통해 해당 쓰레드를 깨울 수 있다.

 - notify()
 notifty는 대기상태인 쓰레드에 대해서 runnable상태로 바꿔준다. 즉, 대기하는 상태에서 실행할 수 있도록 만들어 준다.

 - join() 
 wait()과 비슷한 작업을 하지만 조금 다르다. join()이 하나의 메소드안에 사용되었을경우, 다른Thread들에게는 wait()상태를 준다. 즉 해당된 쓰레드가 끝나야만 다른 쓰레드들이 실행할 수 있도록 하는것이다.
 예를들어 main에서 Thread를 생성 하면 Thread는 main()에 대해서 독립적인 작업을 할 것이다. 또한 main도 마찬가지다. 이때 main이 해당 Thread작업이 끝나고 종료되기를 원할때, Thread 객체.join()을 하면 마치 synchronized같은 작업이 되는 것이다. (Thread객체의 작업수행이 종료 될 때까지 main이 종료되지 않고 기다리기 때문이다.)

- wait(), notify() : synchronized 블록안에서 사용되어야 한다.


하지만 Thread를 사용하는 동안에 위험적인 상황이 발생한다.
바로, Deadlock이라는 것인데, 아래에서 살펴보자.

 - Deadlock
Deadlock은 임계구역이며, 두 가지 작업을 쓰레드들이 하는데 서로 작업이 끝날때까지만을 기다리면서 무한 대기하게 되는 상태를 말한다.

이러한 Deadlock을 방지하는 방법에 대해 살펴보자.

 - Deadlock 최소화
1) 같은 순서로 객체에 접근 할 수 있도록 한다.
객체에 접근하는 순서가 같을 경우 교착상태가 덜 발생한다.

2) 교착상태가 발생하면 서로 깨워주도록 한다.
if 조건문으로 교착상태가 발생하면, 해당 Thread의 wait()상태를 notify()로 깨워주거나 해당 코드를 벗어나도록 코드를 작성 해야한다.


2018년 10월 9일 화요일

Java DataInputStream, DataOutputStream사용

지금까지 Java의 FileInputStream과 FileOutputStream을 사용해서 파일의 내용을 읽고 쓰기 작업을 진행했다.

지금까지 배운것을(FileInputStream과 FileOutputStream내용) 간단히 요약하자면, 파일의 내용을 읽올때 == 스트림을 통해서 파일의 내용에 있는 문자들을 전부 바이트로 읽어들였다. 그래서 컴퓨터는 이를 해석하여, 우리가 읽을 수 있는 문자로 표현했다.
그리고 이 바이트를 읽어 들이는 방법은 여러가지가 있는데, 우리는 한 바이트씩읽기(read)와 텍스트의 한줄씩 읽기(BufferedInputStream 사용)를 통해서 속도의 차이도 비교했었다.

하지만 텍스트파일의 내용을 조금 더 간편하게 읽어오거나 쓰기가 가능하다.
바로 이번에 소개할 DataInputStream / DataOutputStream이다.

스트림에 바이트 단위로 파일의 내용을 읽어들었다면, 이번에는 자바의 기본 자료형에 맞게 파일의 내용을 집어넣어보자.

이를 통해서 우리는 간편하게 스트림에 바이트로 작성하거나 읽어들일 필요가 없이
자바에서 지원하는 기본 자료형의 크기에 맞게 텍스트들을 넣을 수 있게 된 것이다.

역시 우리는 실습을 통해 살펴보는게 빠르다.

1. DataOutputStream을 통해서 새로운파일 생성 → DataInputStream을 통해서 생성한 파일 읽기

  1. package org.java.project1.subproject;
  2.  
  3. import java.io.BufferedInputStream;
  4. import java.io.DataInputStream;
  5.  
  6. import java.io.DataOutputStream;
  7. import java.io.FileInputStream;
  8. import java.io.FileOutputStream;
  9. import java.io.IOException;
  10.  
  11. interface DataStream{
  12.     public void dataWrite(DataOutputStream out) throws IOException;
  13.     public void dataRead(DataInputStream in) throws IOException;
  14. }
  15. class DataInputStreamExam implements DataStream{
  16.     public static String FileName;
  17.     public int[] arrInt = {1, 2, 3};
  18.     public String[] arrStr = {"one하나", "two둘", "three셋"};
  19.     public Double[] arrDouble = {1.0, 2.0, 3.0};
  20.    
  21.     @Override
  22.     public void dataWrite(DataOutputStream out) throws IOException{
  23.         for(int i = 0; i< arrInt.length; i++) {
  24.             out.writeInt(this.arrInt[i]);
  25.             out.writeDouble(this.arrDouble[i]);
  26.             out.writeUTF(this.arrStr[i]);
  27.         }
  28.     }
  29.    
  30.     @Override
  31.     public void dataRead(DataInputStream in) throws IOException{
  32.         String fileContent = "";
  33.         for(int i = 0; i < arrInt.length; i++) {
  34.             fileContent += in.readInt();
  35.             fileContent += in.readDouble();
  36.             fileContent += in.readUTF();
  37.         }
  38.         System.out.println(DataInputStreamExam.FileName + "의 내용 : " + fileContent);
  39.     }
  40.     public void fileRead(DataInputStreamExam obj) throws IOException{
  41.        
  42.     }
  43.     public void fileWrite(DataInputStreamExam obj) throws IOException {
  44.        
  45.     }
  46.    
  47. }
  48. class DataInputStreamExamInfo extends DataInputStreamExam{
  49.    
  50.     public DataInputStreamExamInfo(String FileName) {
  51.         DataInputStreamExam.FileName = FileName;
  52.        
  53.     }
  54.     @Override
  55.     public void fileRead(DataInputStreamExam obj) throws IOException{
  56.         obj.dataRead(new DataInputStream(new BufferedInputStream(new FileInputStream(DataInputStreamExam.FileName))));
  57.     }
  58.     @Override
  59.     public void fileWrite(DataInputStreamExam obj) throws IOException{
  60.         obj.dataWrite(new DataOutputStream(new FileOutputStream(DataInputStreamExam.FileName)));
  61.     }
  62.    
  63. }
  64.  
  65. public class Exam{
  66.     public static void main(String[] args) throws IOException {
  67.         DataInputStreamExam in = new DataInputStreamExamInfo("dataStream.txt");
  68.         in.fileWrite(in);
  69.         in.fileRead(in);
  70.     }
  71. }

▶실행결과
dataStream.txt의 내용 : 11.0one하나22.0two둘33.0three셋



이로써 자바의 기본형으로 바이트로 읽기가 쓰기작업 없이 자동으로 데이터형을 맞춰주어서 편리하게 사용가능했다. 파일의 내용을 한번 살펴볼까?


▶실행파일결과











왜 파일이깨지는가.. 잘못된거같다.. 라고 생각할 수 있으나 당연한것이다.
텍스트의 내용을 바이트단위로 처리해줄때 어떠한 인코딩 형태로 해주었는지에 따라 값이 다르게 나오고 또한 텍스트 파일의 크기도 달라지게 되있다.

그래서 다음시간에는 인코딩형태에따라 파일크기 및 데이터들이 어떻게 저장되는지 살펴보겠다. OutputWriter / InputReader에 대해서 살펴보도록하자.




2018년 10월 2일 화요일

Java FileInputStream / BufferedReader의 스트림 출력 비교

이번에는 FileInputStream과 BufferedReader로 바이트단위를 출력할때 방법에 대해서 살펴보겠다.

1) 1바이트씩 출력하기
2) 한 줄씩 출력하기

위의 2가지경우가 있는데, 예제를 통해서 살펴보자
FileInputStream은 파일의 내용을 읽어오는데, 1바이트씩 문자를 읽어온다.
이와 다르게 BufferedReader는 파일(텍스트)을 한 줄씩(한 라인씩) 읽어서 값들을 출력 할 수 있다.

예제. 1바이트씩 출력한것과 한 줄(텍스트의 한 라인)씩 출력 소요시간 비교
  1. package org.java.project;
  2.  
  3. import java.io.BufferedInputStream;
  4. import java.io.BufferedReader;
  5. import java.io.FileInputStream;
  6. import java.io.FileNotFoundException;
  7. import java.io.IOException;
  8. import java.io.InputStreamReader;
  9. @FunctionalInterface
  10. interface ByteCodePrint{
  11.     public void ByteCodeFunc();
  12. }
  13. abstract class ByteCodes{
  14.     public static String FileReadPath = "data.txt";
  15.    
  16. }
  17. class ByteCodeExam extends ByteCodes {
  18.     public BufferedReader br;
  19.     public long startTime;
  20.     public long endTime;
  21.     public FileInputStream fis;
  22.    
  23.    
  24.     public ByteCodeExam() throws FileNotFoundException{
  25.         super();
  26.         this.fis = new FileInputStream(ByteCodes.FileReadPath);
  27.         this.br = new BufferedReader(new InputStreamReader(this.fis));
  28.     }
  29.     public void fileClose() {
  30.         if(this.fis != null)
  31.             try {
  32.                 this.fis.close();
  33.                 if(this.br != null)
  34.                     this.br.close();
  35.             } catch (IOException e) {
  36.                 // TODO Auto-generated catch block
  37.                 e.printStackTrace();
  38.             }
  39.        
  40.     }
  41.     ByteCodePrint LinePrint = ()  -> {
  42.         String reader = "";
  43.             try{
  44.                 this.startTime = System.currentTimeMillis();
  45.                 while((reader = this.br.readLine()) != null) {
  46.                     System.out.println(reader);
  47.                 }
  48.                 this.endTime = System.currentTimeMillis();
  49.                 System.out.println("LineBuffer의 소요된 시간 : " + (this.endTime - this.startTime) / 1000.0);
  50.             } catch (IOException e) {
  51.                 System.out.println(e.getMessage());
  52.             }
  53.     };
  54.     ByteCodePrint OneBytePrint = () -> {
  55.         try {
  56.             int reader = 0;
  57.             this.startTime = System.currentTimeMillis();
  58.             while( (reader = this.fis.read()) > 0) {
  59.                 System.out.print((char) reader);
  60.             }
  61.             this.endTime = System.currentTimeMillis();
  62.             System.out.println("\nOneByte의 소요된 시간 : " + (this.endTime - this.startTime) / 1000.0);
  63.         } catch( IOException  e) {
  64.             System.out.println(e.getMessage());
  65.         }
  66.     };
  67. }
  68. public class Compile{
  69.      public static void main(String[] args) {
  70.          try {
  71.             ByteCodeExam b = new ByteCodeExam();
  72.            
  73.             b.OneBytePrint.ByteCodeFunc(); // FileInputStream의 객체로 1Byte씩 출력하기
  74.             b.LinePrint.ByteCodeFunc();    // BufferReader의 객체로 한 줄씩 출력하기
  75.             b.fileClose();
  76.         } catch (FileNotFoundException e) {
  77.             System.out.println(e.getMessage());
  78.         }
  79.          
  80.      }
  81. }


실행결과
1) 1Byte씩 출력




2) 한 줄씩 출력















위의 소스코드는 한줄에 A~Z까지 차례대로 번갈아가면서 출력을하는데,
총 717줄까지 존재하며, 717줄까지 출력하는데 걸리는시간을 비교한 예제이다.

Buffer라는 메모리에 한 줄의 문자들을 전부 담아서 한줄씩 출력하는데 걸리는 시간이 더 짧았으며 이는 우리가 파일이나 네트워크상에서 입/출력 스트림을 처리할때에는 buffer를 사용한다면 더 효과적인 방법일것이라는 것을 설명하는 예제이다.

다음시간에는 DataInputStream에 대해서 살펴보도록하겠다.

[Java] N-I/O(Non-Blocking) 파일 읽기 쓰기 - GatheringByteChannel, ScatteringByteChannel, ByteBuffer 사용.

우리는 지금까지 다음과 같이 살펴보았다. 1.  InputStream / OutputStream : 입, 출력 스트림을 바이트로 처리하여 읽기, 쓰기. 2.  FileInputStream / FileOutputStream : 입, 출력 스트림을 ...