4. 루트 브리지, 루트 포트, 데지그네이티드 포트의 결정

 1) 누가 더 작은 Root BID를 가졌는가?

 2) 루트 브리지까지의 Path Cost 값은 누가 더 작은가?

 3) 누구의 BID(Sender BID)가 더 낮은가?

 4) 누구의 포트 ID가 더 낮은가?

 - 브리지나 스위치가 부팅을 하면 이들은 각각의 포트로 BPDU 매 2초마다 내보내면서 서로의 스패닝 트리 정보를 주고받게 된다.

 - BPDU는 스패닝 트리 프로토콜에서 중요한 역할을 한다.

 - BPDU란 스패닝 트리에 대한 여러 가지 정보를 담고 있으면서 매 2초에 한 번 뿌려지는 프레임.


 1) 루트 브리지 선출 과정


 1) 각 스위치는 BID(Bridge ID)를 갖고 있다. (잠깐 여기서 BID개념을 다시 읽고오기)

 2) 맥 어드레스는 편의상 스위치 A는 1111.1111.1111, B는 2222.2222.2222로, C는 3333.3333.3333이라 가정한다.

 3) 낮은 BID를 갖는 스위치가 루트 브리지가 된다.


  (1) 우선 스위치 B와 스위치 C는 서로 BPDU(Bridge Protocol Data Unit)를 주고 받는다. (BPDU란?)

  (2) 브리지가 처음 부팅하고 나서 내보내는 BPDU에는 Sender BID 정보와 자신의 BID를 넣는다.

  (3) 루트 브리지의 BID 역시 자기 자신의 BID를 넣게 된다.

  (왜냐하면 막 부팅 했을 때에 다른 BPDU를 한 번도 받지 못했기 때문에 이 네트워크에 자기 혼자 있다고 생각 한다.)

  (4) 스위치 B와 스위치 C는 루트 브리지 BID를 자기 자신의 BID로 세팅해서 BPDU를 서로 주고 받는다.


  (5) 스위치 B는 스위치 C가 보낸 BPDU의 루트 브리지의 BID를 비교 하여 더 낮은 BID를 루트 브리지로 한다.

  (즉, 스위치 B는 스위치 C에서 받은 BPDU를 무시해 버린다.)

  (6) 스위치 C는 스위치 B로 부터 받은 BPDU의 루트 브리지의 BID를 자신의 루트 브리지 ID와 비교하여 자신의 BPDU에 있는 루트 브리지 BID를 스위치 B의 BID로 바꾸어 다른 곳으로 전송한다.

  (즉, 스위치 B를 루트 브리지로 인정하는 것이다.)


  (7) 스위치 A가 새로 부팅 되고 자신의 BPDU에 루트 브리지의 BID를 자기 BID인 32768.1111.1111.1111로 설정하여 양쪽의 스위치 B와 스위치 C에게 보낸다.

  (8) 스위치 B와 C도 BPDU는 매 2초마다 보내기 때문에 스위치 A에 보내진다. 이때 스위치 B와 C에서 보내온 루트 브리지 BID 필드에는 스위치 BID인 32768.2222.2222.2222 값이 들어있다.

  (9) 모든 스위치들이 BPDU의 루트 브리지 ID를 자신의 루트 브리지 ID와 비교 후 낮은 값을 루트 브리지 ID로 바꾸게 된다.


   (10) 결국 BID가 가장 낮은 값을 가지고 있는 브리지가 루트 브리지가 된다.


  * 이와 같은 과정으로 루트 브리지가 결정이 되는데 만약 스위치 C를 루트 브리지로 설정 하고 싶다면 스위치 C의 BID를 스위치 A의 BID보다 낮은 값으로 만들면 된다.

  * Bridge Priority의 Default 값은 32768이지만 관리자가 임의로 변경할 수 있다.


   (11) Priority 설정 방법 (실습)

   - 루트 브리지 선정이 끝난 스위치

Switch(config)# spanning-tree vlan 1 priority 4096
Switch# show spanning-tree

    ① SwitchA


    ② Switch B


    ③ Switch C

 2) 루트 포트 선출

 - 루트 브리지의 선출이 끝나면 스위치들은 루트 포트의 선출을 시작하게 된다.

  · "모든 Non Root Bridge는 반드시 한 개의 루트 포트(Root Port)를 갖는다."


 3) 데지그네이티드 포트(Designated Port) 선출

 - "세그먼트당 하나씩의 데지그네이티드 포트를 갖는다"

 - 루트 브리지까지의 Path Cost, 즉 세그먼트상에서 Root Path Cost를 서로 비교해서 더 작은 Root Path Cost를 가진 포트가 데지그네이티드 포트로 선출된다.

 - 루트 브리지의 모든 포트들은 언제나 데지그네이티드 포트로 선정된다.

3. 스패닝 트리의 기본적인 과정

 1) 네트워크당 하나의 루트 브리지(Root Bridge)를 갖는다. 

  (여기서 네트워크는 라우터에 의해 나누어지는 브로드캐스트 도메인이 하나의 네트워크를 구성)

  - 하나의 브로드캐스트 도메인에 하나씩의 루트 브리지가 존재

  (1) 루트 브리지(Root Bridge)란?

   - 스패닝 트리 프로토콜을 수행할 때 기준이 되는 브리지(스위치)

 2) 루트 브리지가 아닌 나머지 모든 브리지를 Non Root Bridge라고 한다.

  - Non Root Bridge당 하나씩의 루트 포트(Root Port)를 가져야 한다.

  - 루트 포트란 루트 브리지에 가장 빨리 갈 수 있는 포트를 말한다. 즉 루트 브리지쪽에 가장 가까운 포트

  - 네트워크당 하나씩의 루트 브리지가 존재하므로 루트 브리지를 제외한 나머지 모든 브리지는 자동으로 Non Root Bridge가 된다.

  - 나버지 브리지들은 루트 브리지쪽으로 가장 가까이 있는 루트 포트를 하나씩 지정해 주어야 한다.

 3) 세그먼트당 하나씩의 데지그네이티드 포트(Designated Port)를 갖는다.

  - 세그먼트란 브리지 또는 스위치 간에 서로 연결된 링크

  - 브리지나 스위치가 서로 연결되어 있을 때 이 세그먼트에서 반드시 한 포트는 Designated Port로 선출되어야 한다.

  * 스패닝 트리 프로토콜에서 루트 포트나 데지그네이티드 포트가 아닌 나머지 모든 포트는 다 막아버린다!

2. 스패닝 트리 프로토콜(Spanning Tree Protocol : STP)

 · 스위치나 브리지에서 발생하는 루핑을 막아주기 위한 프로토콜

 · 즉, 스위치나 브리지 구성에서 출발지부터 목적지까지의 경로가 두 개 이상 존재할 때 한 개의 경로만을 남겨두고 나머지는 모두 끊어두었다가 사용하던 경로에 문제가 발생하면 그때 끊어 두었던 경로를 하나씩 살린다.


 1) 브리지 ID (Bridge ID)

  · 브리지나 스위치들이 통신할 때 서로를 확인하기 위해 하나씩 가지고 있는 번호

 

  - 브리지 ID는 16비트의 브리지 우선 순위와 48비트의 브리지 MAC 주소로 만들어진다.

  - 맨 앞에 'Bridge Priority'가 오고, 그 뒤에 바로 'MAC Address'가 오는 것이 Bridge ID이다.

  (1) Bridge Priority

   - 16 비트 ( 0 ~ 65535 )

   - Default Bridge Priority (32768)

  (2) Path Cost

   - '목적지까지 가는 경로에서 거치게되는 각 링크들로 부담되는 총 비용'

   - IEEE 802.1D에서는 이 Cost 값을 계산할 때 1000Mbps를 두 장비 사이의 링크 대역폭으로 나눈 값을 사용했다.

   - ex) 두 스위치가 10Mbps로 연결되어 있다고 가정했을 때 Path Cost 는?

   ∴ Path Cost는 1000Mbps를 둘 사이의 링크 대역폭으로 나눈 값이다. 1000/100 = 10


* Redundant Topology의 문제점

  (1) 브로드캐스트 스톰(Broadcast Storm)

   - 하나의 패킷이 브로드캐스팅되어 수신되고, 이를 다시 하나 이상의 수신자에 의해 또다시 브로드캐스팅 되어 나타나는 폭주 상태

   - 루프(폐쇄경로)가 제거 또는 회피되지 않은 네트워크에서 일어날 수 있음

  (2) MAC 주소 테이블의 불안전성 

   - 루핑이 발생하면 Mac Address Table은 지속적으로 업데이트가 되면서 바뀌게 된다. (신뢰성 ↓)


∴ 해결책 Spanning Tree Protocol

1. 스위치와 브리지

 1) 스위치, 브리지란?

   · 스위치, 브리지는 2 이상의 링크계층 네트워크를 결합하여 LAN을 확장 구성하는 장비

    - 스위치는 여러 개의 포트를 가진 고성능 브리지(Multiport Bridge)

     - 단순 브리지는 2 포트 스위치로 볼 수 있음

  (1) 브리지

   - 소프트웨어 기반

   - 브리지 당 1 개의 스패닝 트리

   - 브리지 당 수개의 포트

   - 프레임 저장 후 전달

   - 한 번에 하나씩 프레임 전달

   - 각 포트에 전체용량을 쪼개어 할당 (전체용량을 각 포트가 공유하므로)

  (2) 스위치

   - 하드웨어 기반

   - 스위치 당 다수 스패닝 트리

   - 브리지 보다 훨씬 많은 포트 (다중 포트 브리지)

   - 프레임 저장 후 전달 뿐만 아니라 컷 스루 스위칭 방식도 가능

   - 한 번에 여러 프레임을 병렬로 동시 전달 가능

   - 각 포트에 전체용량을 동일하게 전용으로 할당


 2) LAN 스위치 주요 특징

  (1) 속도가 빠름(소프트웨어 보다 하드웨어적으로 수행)

   - CPU에 의한 소프트웨어 처리가 아닌 ASIC 하드웨어에 의한 수행으로 속도가 빠름

  (2) 네트워크를 미세하게 분할가능(MicroSegmentation)

   - 네트워크를 미세하게 분할하여 실사용자에게 대역폭을 최대한 할당할 수 있음

  (3) 각 포트 마다 전용 채널 할당 (Dedicated) 및 전이중 방식 사용 (Full-Duplex)

   - 각 포트 마다, 전용의 대역폭 채널을 할당, 전이중 방식의 데이터 통신

  (4) 브리지 보다 많은 수의 포트 보유 가능(Multiport Bridge)

   - 브리지는 최대 16개의 포트를 갖으나, 스위치는 수십 수백개의 포트도 가

  (5) 특정 트래픽을 고립시킬 수 있음(Isolated)

   - 특정 세그먼트로의 트래픽을 고립시킴에 의해 전체 가용 대역폭을 증가

    · 혼잡이 특히 심한 네트워크를 더 작은 세그먼트들로 나누어 통신트래픽을 고루 분산시켜 전체적인 효율을 개선시킬 수 있음

  (6) 수신된 프레임을 빠르게 포워딩하는 방식(Fast Forwarding)

   - 주로 Cut-through Switching 방식 사용

  (7) 2계층에서 동작(L2 스위치)

   - OSI 7계층모델의 관점에서 LAN Switch는 2계층(데이터링크 계층)에서 동작

    · 단, 요즈음은 2 ~ 3계층 기능 모두 가능한(Multi-layered) 장비도 출현

    · TP(Twisted Pair) 모듈과 FDDI 모듈등 여러개의 독립된 기능을 하나로 모을 수 있고 또한 하나에 브리지와 라우터 기능을 복합화시킬 수 있다.

  (8) LAN 스위치에 의한 가상 LAN 기능 구현(Virtual LAN)

   - 구성의 유연함을 제공 


 3) 스위치의 기능

  (1) 주소 학습(Learning)

   - 스위치는 자신의 포트에 연결된 PC가 통신을 위해서 프레임을 내보내면 그때 이 PC의 MAC Address를 자신의 MAC Address Table에 저장해놓는다.

  (2) 플로딩(Floooding)

   - 프레임을 모든 포트에 전달

  (3) 포워딩(Forwarding)

   - 스위치나 브리지가 목적지의 MAC Address를 자신의 MAC Address Table에 가지고 있고, 이 목적지가 출발지와 다른 세그먼트에 존재하는 경우 발생

   - 프레임을 해당 포트에만 전달

  (4) 필터링(Filtering)

   - 브리지나 스위치가 목적지의 MAC Address를 알고 있고, 출발지와 목적지가 같은 세그먼트 상에 있는 경우 발생

   - 콜리전 도메인(Collision Domain)을 나눌 수 있는 기능을 제공

  (5) Aging

   - MAC Address를 MAC Address Table에 저장하기 시작한 이후 300초까지 정보를 갖고 있는다.

   - 300초가 지나도록 더 이상 그 출발지 주소를 가진 프레임이 들어오지 않으면 Table에서 삭제


 * 브리지에서 프레임의 흐름


 4) 프레임 전송모드




  (1) Store and Forwarding

   - 스위치나 브리지가 일단 들어오는 프레임을 전부 받아들인 다음 처리를 시작하는 방식

   - 에러는 없는지, 출발지 주소는 어디인지, 목적지 주소는 어디인지 파악

   - 긴 Latency

  (2) Cut-through

   - 스위치가 들어오는 프레임의 목적지 주소만을 본 다음 바로 전송 처리를 시작하는 방식

   - 48비트만을 확인

   - SoF보다 적은 Latency

  (3) Fragment-Free

   - 처음 512비트를 보고 판단하는 방식

   - 에러 감지 기능 제공

  (4) Adaptive Cut-through

   - 프레임에서 발생한 오류가 미리 정의한 한계 값을 넘지 않는 경우에는 Cut-through를 수행하고 이 값을 넘어서면 Store-and-forward 모드로 전환되는 방식

개요

 1. 스위치와 브리지

  1) 스위치, 브리지란?

  2) LAN 스위치의 주요 특징

  3) 스위치의 기능

  4) 프레임 전송모드


 2. 스패닝 트리프로토콜(Spanning Tree Protocol)의 이해

  1) 브리지 ID(Bridge ID)

   (1) Bridge Priority

   (2) Path Cost

  * Redundant Topology의 문제점


 3. 스패닝 트리의 기본적인 과정

  1) 네트워크당 하나의 루트 브리지(Root Bridge)를 갖는다.

  2) 루트 브리지가 아닌 나머지 모든 브리지(Non Root Bridge)는 무조건 하나씩의 루트 포트(Root Port)를 갖는다.

  3) 세그먼트(Segment)당 하나씩의 데지그네이티드 포트(Designated Port)를 갖는다.


 4. 루트 브리지, 루트 포트, 데지그네이티드 포트의 결정

  1) 루트 브리지 선출 과정

  2) 루트 포트 선출

  3) 데지그네이티드 포트 선출


 5. 스패닝 트리 프로토콜의 5가지 상태 변화




  1. 스트림(Stream)이란?
    • 일차원적인 데이터의 흐름
    • 스트림에 데이터를 쓸 수 있고, 스트림에서 데이터를 읽을 수 있다.
  2. 스트림의 특징
    1. 스르림은 FIFO 구조이다.
      • FIFO 구조란 먼저 들어간 것이 먼저 나오는 형태로서 데이터의 순서가 바뀌지 않는다는 특징을 가지고있다.
    2. 스트림은 단방향이다.
      • 자바에서 스트림은 읽기, 쓰기동시에 되지 않는다. 따라서 읽기, 쓰기가 필요하다면 읽는 스트림과 쓰는 스트림을 하나씩 열어 사용해야 한다.
    3. 스트림은 지연될 수 있다.
      • 스트림은 넣어진 데이터가 처리되기 전까지는 스트림에 사용되는 스레드는 지연상태에 빠진다.
      • 즉, 네트워크 내에서는 데이터가 모두 전송되기 전까지 네트워크 스레드는 지연상태가 된다.
  3. 스트림의 분류
    1. 데이터 전송 방향에 의한 분류
      1. 입력 스트림(InputStream)
        • 프로그램으로 들어오는 스트림
      2. 출력 스트림(OutputStream)
        • 프로그램에서 밖에서 나가는 스트림
    2. 데이터 전송 단위에 의한 분류
      1. 문자 스트림(character stream)
        • 한 문자(2 byte) 단위로 읽고, 쓸 수 있는 스트림
      2. 바이트 스트림(byte stream)
        • 한 byte 단위로 읽고, 쓸 수 있는 스트림
  4. File Class
    • File 클래스는 파일 혹은 디렉토리의 등록정보를 표현하는 클래스
    • File 클래스는 실제 파일의 내용을 포함하지 않는다.
    • File 객체는 실제 파일의 존재여부와 상관없이 생성된다.
    1. 생성자

      생성자 

      설명 

      File(String pathname) 

      문자열 Pathname을 가지고 경로를 생성하여 File 객체를 생성한다. 

      File(String parent, String child) 

      Parent와 child 문자열을 연결한 문자열로 경로를 생성하여 File 객체를 생성한다. 

      File(File parent, String child) 

      Parent의 객체와 child 문자열로 경로를 생성하여 File 객체를 생성한다. 



    2. 메소드

    3. 반환형

      메소드 

      설명 

      boolean

      canRead() 

      파일을 읽을 수 있으면 true,

      그렇지 않으면 false 

      canWrite() 

      파일을 쓸 수 있으면 true,

      그렇지 않으면 false 

      createNewFile() 

      파일을 새로 생성하면 true,

      그렇지 않으면 false 

      delete() 

      파일을 지우면 true,

      그렇지 않으면 false 

      exists()

      파일이나 디렉토리가 존재하면 true,

      그렇지 않으면 false 

      String

      getAbsolutePath() 

      파일의 절대 경로를 반환한다. 

      getCanonicaPath() 

      파일의 정규 경로를 반환한다. 

      getName()

      파일명을 반환한다. 

      boolean 

      isDirectory() 

      디렉토리면 true,

      그렇지 않으면 false 

      isFile() 

      파일이면 true,

      그렇지 않으면 false 

      long 

      lastModified()

      1970년 1월 1일부터 현재까지의 시간을 밀리세컨드 초로 반환 

      length() 

      파일의 크기를 바이트로 반환 

      String[] 

      list() 

      특정 디렉토리를 생성하면 true,

      디렉토리가 있어서 생성하지 못하면 false 

      boolean 

      mkdir() 

      디렉토리를 생성하면 true,

      디렉토리가 있어서 생성하지 못하면 false 

      renameTo(File dest) 

      dest 파일 객체로 이름을 바꾸면 true,

      그렇지 않으면 false 


      • 파일 정보 출력 예제 1

        import java.io.File; public class FileEx1 { public static void main(String[] args) { File file = new File("경로/hello.txt"); System.out.println("파일인지 여부 : " + file.isFile()); System.out.println("디렉토리인지 여부 : " + file.isDirectory()); System.out.println("상대경로 : " + file.getPath()); System.out.println("절대경로 : " + file.getAbsolutePath()); System.out.println("디렉토리 혹은 파일의 이름 : " + file.getName()); System.out.println("파일의 길이 : " + file.length()); System.out.println("파일의 최종 수정 날짜 : " + file.lastModified()); } }

      • 파일 목록 출력 예제 2
        import java.io.File;
        
        public class FileEx2 {
        	public static void main(String[] args) {
        		File directory = new File("디렉토리 경로");
        		
        		if(directory.exists()){
        			if(directory.isDirectory()){
        				// 현재 디렉토리내의 모든 파일 디렉토리의 이름 얻기
        				String[] fileNameList = directory.list();
        				// for (자료형 index : 변수명)
        				for (String fileName : fileNameList){
        					System.out.println("파일 이름 : " + fileName);
        				}
        			}
        		}
        	}
        }
        
        
      • 파일, 디렉토리 생성 및 삭제 변경
      • import java.io.File; import java.io.IOException; public class FileEx3 { public static void main(String[] args) { // 파일 생성 File f1 = new File("경로명/newFile.txt"); if (f1.exists()) { System.out.println("파일 이름 : " + f1.getName()); } else { try { if (f1.createNewFile()) { System.out.println("새로운 파일을 만들었습니다."); } } catch (IOException e) { e.printStackTrace(); } } File f2 = new File("경로명/newDirectory"); if (f2.exists()) { f2.mkdir(); } else { System.out.println("디렉토리 이름 : " + f2.getPath()); } //파일 혹은 디렉토리 삭제 File f3 = new File("경로명/text.txt"); if(f3.exists()){ f3.delete(); } //파일 혹은 디렉토리 이름 변경 File src = new File("경로명/newFile.txt"); File dest = new File("경로명/dest.txt"); File dest2 = new File("경로명/dest2.txt"); if(src.exists()){ src.renameTo(dest); src.renameTo(dest2); } if(f2.isDirectory()){ String dir[] = f2.list(); System.out.println("\n \n Dir Content:===========\n"); for (String dirs : dir){ System.out.println("dirs : " + dirs); } } } }

  5. Byte Stream의 상속 관계
  6. Byte Stream의 주요 메소드

     InputStream

    close() 

    Device와 연결된 스트림 해제 

    read() 

    1 byte씩 읽어서 바이트 값 반환 

    read(byte[] b)

    1 byte씩 읽어서 byte 배열에 저장하고, 배열에 저장된 개수를 반환한다.

    스트림의 끝에 도달하면 -1을 반환 

    read(byte[], int start, int length) 

    데이터를 length만큼 읽어서 byte[]에 start 위치에 저장하고 읽은 수 만큼 반환한다.

     OutputStream

    close() 

    Device와 연결된 스트림 해제 

    write(int i) 

    1 byte 기록한다. 

    write(byte[] b) 

    byte배열에 저장된 data를 기록한다. 

    write(byte[], int offset, int length) 

    byte배열에 저장된 data를 offset위치에서 length만큼 기록한다.


  7. FileInputStream과 FileOutputStream
    • 바이트 단위로 파일 내용을 읽어 들이거나, 파일에 내용을 기록할 때 사용하는 스트림

    1. 생성자

      생성자 

      설명 

      FileInputStream(String fileName) 

      fileName의 파일객체를 생성하고 InputStream을 연결 

      FileInputStream(File file) 

      file 객체에 inputStream을 연결 

      FileOutputStream(String fileName) 

      fileName의 파일객체를 생성하고 outputStream을 연결 

      FileOutputStream(String name, boolean append)

      append가 true이면 파일에 내용을 이어쓰고, append가 false이면 덮어쓴다. 

      FileOutputStream(File file) 

      file 객체에 outputStream을 연결 

      FileOutputStream(File file, boolean append) 

      append가 true이면 파일에 내용을 이어쓰고, append가 false이면 덮어쓴다. 


      • FileInputStream 예제

        import java.io.FileNotFoundException;
        import java.io.FileOutputStream;
        import java.io.IOException;
        
        public class FileOutputStreamEx {
        	public static void main(String[] args) {
        		FileOutputStream fos = null;
        
        		try {
        			// FileNotFoundException 예외처리
        			fos = new FileOutputStream("c:\\fileout.txt");
        			String message = "Hello FileOutPutStream!!";
        			// IOException 예외처리
        			fos.write(message.getBytes());
        
        		} catch (FileNotFoundException e) {
        			e.printStackTrace();
        		} catch (IOException e) {
        			e.printStackTrace();
        		} finally {
        			try {
        				// FileOutputStream 스트림 해제
        				fos.close();
        			} catch (IOException e) {
        				e.printStackTrace();
        			}
        			
        		}
        
        	}
        }
        

      • 파일 복사 예제 1 : 1 byte 단위로 복사
        import java.io.File;
        import java.io.FileInputStream;
        import java.io.FileNotFoundException;
        import java.io.FileOutputStream;
        import java.io.IOException;
        
        public class FileCopyEx1 {
        	public static void main(String[] args) {
        		System.out.println("파일복사 시작");
        
        		long start = System.currentTimeMillis();
        		FileInputStream src = null;
        		FileOutputStream dest = null;
        		try {
        			// 원본파일을 읽기 위한 FileInputStream 객체 생성
        			src = new FileInputStream(new File("src.zip"));
        			// 복사본 파일을 생성하기 위한 FileOutputStream 객체 생성
        			dest = new FileOutputStream(new File("dest.zip"));
        
        			// FileInputStream을 통해서 읽어들인 값을 저장할 변수
        			int readValue = 0;
        
        			// FileInputStream의 read()메소드를 통해서 읽어들인 값을 readValue에 저장
        			while ((readValue = src.read()) != -1) {
        				// readValue에 저장된 값을 FileOutputStream의 write() 메소드를 통해서 파일에 기록
        				dest.write(readValue);
        			}
        		} catch (FileNotFoundException e) {
        			e.printStackTrace();
        		} catch (IOException e) {
        			e.printStackTrace();
        		} finally {
        			try {
        				if (dest != null) {
        					dest.close();
        				}
        				if (src != null) {
        					src.close();
        				}
        			} catch (IOException e) {
        				e.printStackTrace();
        			}
        		}
        		long end = System.currentTimeMillis();
        		long copyTime = (end - start) / 1000;
        		System.out.println("걸린 시간 : " + copyTime + " 초");
        	}
        }
        
      • 파일 복사 예제 2 : byte[] 를 이용한 복사
        import java.io.FileInputStream;
        import java.io.FileNotFoundException;
        import java.io.FileOutputStream;
        import java.io.IOException;
        
        public class FileCopyEx2 {
        	public static void main(String[] args) {
        		System.out.println("파일 복사 시작");
        		long start = System.currentTimeMillis();
        		FileInputStream src = null;
        		FileOutputStream dest = null;
        
        		try {
        			src = new FileInputStream("src.zip");
        			dest = new FileOutputStream("dest.zip");
        			// 임시저장소에 저장된 data의 전체갯수를 저장할 변수
        			int length = 0;
        			// 임시 저장소로 사용될 byte[] 배열 선언
        			byte[] buffer = new byte[1024 * 8];
        			// InputStream을 통해서 읽어들인 data를 임시저장소에 쌓고 저장된 data의 갯수를 length에 저장한다.
        			while ((length = src.read(buffer)) != -1) {
        				// outputStream을 통해서 임시저장소에 쌓여있는
        				// data을 length만큼 파일에 기록한다.
        				dest.write(buffer, 0, length);
        			}
        		} catch (FileNotFoundException e) {
        			e.printStackTrace();
        		} catch (IOException e) {
        			e.printStackTrace();
        		} finally {
        			try {
        				if (dest != null) {
        					dest.close();
        				}
        				if (src != null) {
        					src.close();
        				}
        			} catch (IOException e) {
        				// TODO Auto-generated catch block
        				e.printStackTrace();
        			}
        		}
        		long end = System.currentTimeMillis();
        		long copyTime = (end - start) / 1000;
        		System.out.println("걸린 시간 : " + copyTime + " 초");
        	}
        }
        
  8. DataInputStream과 DataOutputStream
    • 특정 데이터 타입과 포맷을 유지한 채 데이터를 기록하고 읽어올 수 있는 스트림
    • 특정 데이터 타입과 포맷에 맞게 읽고 쓸 수 있는 readBoolean(), writeBoolean(boolean v), readInt(), writeInt(int v), readUTF(), writeUTF(Strring s)등 의 메소드를 제공한다.
    1. 생성자
      • DataInputStream(InputStream stream)
      • DataOutputStream(OutputStream stream)
        1. DataOutputStream 활용 예제 : 여러 가지 자료형의 데이터를 파일에 기록
        2. DataInputStream 활용 예제 : 특정 자료형의 포맷과 값을 유지한 채로 읽어오기
  9. 문자 스트림
    • 바이트 스트림에 추가하여 Reader와 Writer 클래스를 제공하는데, 이것은 2바이트를 입출력 할 수 있는 문자 기반 스트림이다.
    • 바이트 스트림은 1바이트를 입출력하기 때문에 일반적으로 영문자로 구성된 파일, 동영상 파일, 음악 파일의 입출력 등에 적합한 스트림이다.
    • 문자 스트림은 2바이트를 입출력하기 때문에 세계 모든 언어로 구성된 파일을 입출력하기에 적합하다.
  10. 문자 Stream의 상속관계
  11. 문자 Stream의 주요 메소드
    • Reader의 주요 메소드
    • Writer의 주요 메소드
  12. FileReader와 FileWriter
    • 문자 단위로 파일 내용을 읽어 들이거나, 파일에 내용을 기록할 때 사용하는 스트림
    • 텍스트 기반의 파일만을 읽고 쓸 수 있다.
    1. FileReader의 생성자
    2. FileWriter의 생성자
    • FileWriter 활용 예제 : 파일에 텍스트 기록하기
    • FileReader 활용 예제 : 파일로부터 한 문자씩 텍스트 읽기
  13. Bridge 스트림과 Bufferd스트림
    • 브릿지(Bridge) 스트림 : 바이트 스트림을 문자스트림으로 변환하는 스트림
    1. InputStreamReader : 바이트 입력 스트림을 문자 입력스트림으로 변환
      InputStreamReader isr = new InputStreamReader(System.in);
    2. OutputStreamWriter : 바이트 출력 스트림을 문자 출력스트림으로 변환
      FileOutputStream fos = new FileOutputStream("hello.txt");
      OutputStreamWriter osw = new OutputStreamWriter(fos);
    • Buffered 스트림 : 스트림의 읽고 쓰는 성능을 개선하기 위해 스트림 내부에 버퍼를 가지고있는 스트림
      1. BufferedInputStream, BufferedOutputStream
      2. BufferedReader, BufferedWriter
    • BufferedReader 스트림
      • BufferedReader은 readLine()메소드 제공
      • readLine()메소드는 스트림으로부터 한 라인씩 읽을 수 있다.
      • readLine()메소드는 문자열을 반환하면, 스트림의 긑에 도달하면 null을 리턴한다.
      • 개행문자의 앞까지 읽어온다.
    • BufferedWriter 활용예제 : 텍스트에 문자 기록하기
    • BufferedReader 활용예제 : 텍스트로부터 문자읽기
  14. PrintStream과 PrintWriter
    1. PrintStream
      • PrintStream은 모든 자료형을 출력할 수 있는 print(), println() 메소드가 오버로딩 되어 있다.
      • 프로그램이 시작되면 장치와 연결된 출력스트림인 System.out, System.err 객체가 PrintStream 객체이다.
      • 다른 스트림과는 다르게 플러쉬 기능을 자동으로 처리할 수 있는 생성자를 가지고 있다.
    2. PrintWriter
      • PrintWriter 클래스는 다른 스트림과 다르게 바이트 출력 스트림과 문자 출력 스트림을 가지고 객체를 생성할 수 있는 클래스이다.
      • 자동 플러쉬 기능을 가지고 있다.
      • PrintWriter 클래스의 생성자에는 FileNotFoundException 예외를 발생하기 때문에 반드시 예외처리를 해야 한다.
      • PrintStream 활용 예제 : 파일에 문자 기록하기
      • PrintWriter 활용 예제 : 파일에 문자 기록하기
  15. Scanner Class
    • Scanner 클래스는 입력 값(문자열, 파일, 입력 스트림)을 정규 표현식으로 구분하여 문자열이나 기본 데이터 타입으로 토큰 할 수 있는 클래스이다. 정규 표현식이란 언어를 표현 할 수 있는 문자식을 말한다.
    • 이렇게 구분된 토큰은 다양한 nextXXX() 메소드를 사용하여 다른 타입의 값으로 바뀌게 된다. 
    1. 생성자
      • Scanner 클래스는 매개변수로 네 가지 타입을 갖는다.
      • 네 가지 타입 - File, InputStream, Readable, String
      • Scanner 클래스는 네 가지 타입을 매개변수로 구분자나 구분 패턴을 사용하여 문자열이나 기본 데이터 타입으로 토큰 할 수 있는 클래스이다.
    2. 주요 메소드
    • 키보드로 입력한 값을 int로 변환한 예
    • File 클래스를 이용한 double로 변환한 예
    • 문자열을 구분 패턴으로 변환한 예
    • 스트림을 이용한 구분 패턴으로 변환한 예
    • Scanner 활용 예제 1 : 키보드로부터 숫자 입력 받기
    • Scanner 활용 예제 2 : 파일로부터 읽어오기
    • Scanner 활용 예제 3 : URL로부터 읽어오기
    • Scanner 활용 예제 4 : String으로부터 읽어오기
  16. 객체의 직렬화
    • 가상머신 안에 존재하는 특정 객체(객체의 메모리와 객체에 대한 정보)를 바이트 형태로 변환하는 것.
    • 객체의 직렬화를 통해 프로그램이 실행되는 동안 생성된 객체를 스트림을 이용해서 지속적으로 보관하거나 전송할 수 있다.
    • 직렬화 가능한 클래스를 만드는 방법
      1. Serializable 인터페이스를 이용
      2. Externalizable 인터페이스를 이용
      • 직렬화 예제 : 객체 직렬화하기
  17. ObjectStream(객체 스트림)
    • ObjectOutputStream과 ObjectInputStream은 각각 객체를 직렬화, 역직렬화하는 메소드를 제공하는 스트림이다.
    • ObjectStream의 주요 생성자
      • ObjectOutputStream(OutputStream os)
      • ObjectInputStream(InputStream is)
    • ObjectStream의 주요 메소드
      • ObjectOutputStream의 void writeObject(Object obj)
        객체를 직렬화하고 스트림을 통해서 기록(전송)한다.
      • ObjectInputStream의 Object readObject()
        스트림을 통해 읽어들인 직렬화된 객체를 역직렬화(객체로 복원)한다.
        반환형이 Object이기 때문에 해당 객체 타입으로 캐스팅해야 한다.
      • 참고 : transient (Serializable 인터페이스를 상속받았을 경우)
        멤버변수를 직렬화 대상에서 제외하고자 할 때 사용한다.
        멤버 변수 앞에 명시한다.
    • ObjectOutputStream 활용예제 : 직렬화도니 객체를 파일에 저장하기


1006.pkt


개요


 6. 액세스리스트

  1) 액세스 리스트란?

  2) 액세스 리스트의 사용 목적

  3) 액세스 리스트의 적용 대상

  4) 액세스 리스트의 규칙

  5) 액세스 리스트의 종류

   (1) Standard Access List

   (2) Extended Access List

   (3) Wildcard Mask

  6) 액세스 리스트 관련 명령어

  7) 액세스 리스트 사용 방법

  8) 액세스 리스트 실습


6. 엑세스리스트(Access List, Access Control List, ACL)

 1) 엑세스 리스트란?

    • 네트워크의 문지기
    • 라우터 등의 장비에서 패킷 필터링, 패킷 분류를 결정짓는 일련의 규칙 목록들


 2) 액세스 리스트의 사용 목적

    • 트래픽 제어
      • 가장 일반적인 용도, 어떤 인터페이스를 통과(in, out)하는 패킷 Traffic을 제어
    • 보안용
    • 패킷의 식별용 등

 3) 액세스 리스트 적용 대상
    • Interface에 적용 -> Access Group
      • 이 경우의 Access List는 입력 또는 출력 인터페이스에 적용
    • Proticol에 적용 -> Distribute List
    • 입력/출력 인터페이스 및 프로토콜 각각에 하나의 ACL만 적용 가능

 4) 액세스 리스트의 규칙 **
  1. access-list 윗줄부터 하나씩 차례로 수행된다.
  2. 엑세스 리스트의 맨 마지막에 Line에 "permit any"를 넣지 않을 경우에는 default로, 
    어느 엑세스 리스트와 match되지 않은 나머지 모든 addressdeny 된다.
    • 즉, access-list의 맨 마지막 줄에는, default 값으로 deny all (deny any)이 지정되어있는 것으로 간주
  3. 엑세스 리스트의 새로운 line 은 항상 맨 마지막으로 추가되므로 access-list line의 선택적 추가(selective add)나 제어(remove)가 불가능하다.
    • access-list를 수정할 수 없고, 처음 초기 세팅부터 다시 시작해야 함
  4. Interface에 대한 access list의 정의(define)가 되지 않은 경우
    (즉, Interface에 access-group 명령이 들어있지 않은 경우)
    결과는 permit any가 된다.
    • 즉, access list가 정의 되지 않은 interface는 default값으로 permit any가 된다.

 5) 엑세스 리스트의 종류

 

  (1) Standard ACL (표준 액세스 리스트)

    • 출발지 IP 주소만으로 검사
      • IP 주소 및 네트워크 주소로 필터링
    • Access-List-Number (표준 ACL 번호)
      • 1 ~ 99 또는 1300 ~ 1999 (IP)
      • 300 ~ 399 (DECnet),
      • 800 ~ 899 (IPX),
      • 1000 ~ 1099 (IPX SAP) 등
    • 사용문법 : access-list access-list-number {permit | deny} source-address [wildcard-mask]
    • 사용예시 : access-list 1 permit 210.130.50.2
    • 사용위치 : 최대한 목적지에 가깝게 설정

  - Inbound Access List & Outbound Access List


  (2) Extended ACL (확장 액세스 리스트)

    • 목적지 및 출발지의 주소, 프로토콜, 포트번호 등을 모두 검사 (폭넓은 확장 가능)
      • IP 주소 뿐만아니라 TCPUDP의 포트 번호도 검사하여 제어
      • ICMP code 및 type 등
    • Access-list-number (Extended ACL 번호)
      • 100 ~ 199 또는 2000 ~ 2699(IP)
      • 900 ~ 999 (IPX) 등
    • 사용문법 : access-list access-list-number {permit | deny} protocol source-addess source-wildcard-mask destination-address destination-wildcard-mask operator port
    • 사용예시 : access-list 101 permit tcp 210.70.20.230 0.0.0.0 210.70.10.33 0.0.0.0 eq www
    • 사용위치 : 최대한 출발지에 가깝게 설정

  - Extended Access List의 동작



 6) Wildcard Mask
    • IP 주소에서 비트 단위의 마스크를 의미
      • '0'은 해당 비트 위치에서 정해진 비트 값과 정확하게 일치해야 함 (검사 필요)
      • '1'은 해당 비트 위치에서 어떠한 비트 값과도 일치 할 수 있음 (검사 불필요)
        • 즉, 비트 '1'값이면, 0 또는 1 모두 허용
    • 예시) 192.168.30.0 에서, Wildcard Mask가 0.0.0.255일 때 허용 가능한 IP 주소
      • 192.168.30.0 ~ 192.168.30.255 까지 모두 가능함을 의미
        (255는 2진수로 1111 1111)
      • 192.168.0.1 0.0.0.0, host 192.168.0.1은 호스트 주소 192.168.0.1 하나 만을 대상으로 함
      • 0.0.0.0 255.255.255.255, any는 모든 호스트를 대상으로 함

 7) Access-List 관련 명령어 
    • ACL 설정 명령어 
      • access-list
    • ACL 활성화 명령
      • access-group
    • ACL를 설정한 내용확인 명령어
      • show ip access-list

 8) 사용 방법
    • access-list 정의 생성 -> Interface별 , protocol별로 각각 정의된 access-list 적용(access-group)
      1. ACL 설정
      2. ACl 적용할 인터페이스 선택
      3. 선택한 인터페이스에서 ACL 활성화
    • 적어도 1이상의 '허용' 구문을 포함해야함
      • 그렇지 않으면 모든 패킷을 차단하게 됨


   (1) Access-list 정의 생성

    ① Standard ACL 

    • Router(config)# access-list access-list-number { permit | deny } source [source-wildcard]

      • access-list-number

        • ACL의 종류를 구분하기 위한 것 1 ~ 99(Standard), 100 ~ 199(Extended)

      • { permit | deny }

        • Access-list의 조건에 일치 할 경우 'permit' 또는 'deny'를 수행하도록 함

      • source

        • 출발지 IP 주소

      • source-wildcard

        • 해당 network의 prefix를 제한해 주는 역할 

    • source [source-wildcard]
      • Any
        • 0.0.0.0 255.255.255.255의 역할을 대신 함
        • 모든 IP address를 다 포함
      • Host
        • 192.168.30.2 0.0.0.0를 host 192.168.30.2로 줄여 쓸 수 있다.
        • 해당 IP에만 조건을 적용
   ② Extended ACL
    • Router(config)# access-list access-list-number {permit | deny}
      source [source-wildcard] destination [destination-wildcard]
      operator established port
      • access-list-number
        • Extended ACL에서는 100 ~ 199까지 사용
      • { permit | deny }
        • Access-list의 조건에 일치 할 경우 'permit' 또는 'deny'를 수행하도록 함
      • protocol
        • IP와 ICMP, IGRP, TCP, UDP등의 프로토콜
      • source
        • 출발지 IP 주소
      • source-wildcard
        • 해당 network의 prefix를 제한해 주는 역할
      • destination
        • 목적지 IP 주소
      • destination-wildcard
        • 해당 network의 prefix를 제한해 주는 역할
      • operator
        • protocol에서 기입한 포트번호에 대한 비교 연산을 위한 것
          • gr (grater than)
          • lt (less than)
          • eq (equal)
          • neq (not equal)
      • established
        • TCP 데이터그램이 ACK나 RST bit이 set되어 들어오는 경우에만 match가 발생하게 된다.
        • 해당 네트워크에 있는 호스트들은 밖으로 나갈 수 있고, 밖에서는 해당 네트워크로 들어올 수 없게 하는 기능
      • port
        • 위의 프로토콜에 따른 port 분류 번호


   (2) Access-list 적용(Access-group)

    • Router(config-if)# ip access-group access-list-number { in | out }

    ① Standard ACL (Ex)

      • PC C를 제외한 210.240.100.0 네트워크의 모든 PC는 PC A를 접속 할 수 있다.

      • 210.240.150.0 네트워크에서는 PC B를 포함해서 나머지 모든 PC들이 PC A를 접속할 수 있다.

      • 인터넷의 모든 PC는 PC A를 접속할 수 있다.

      • access-list 1 deny 210.240.100.5

      • access-list 1 permit 210.240.100.0 0.0.0.255

      • access-list 1 permit 210.240.150.0 0.0.0.255

      • int fa 0

      • ip access-group 1 out



    ② Extended ACL (Ex)

      • 라우터 A를 기준 (Extended ACL 적용)

        • 내부 네트워크에서는 자유롭게 통신이 가능

        • 외부 네트워크에서 들어오는 웹서버를 허용

        • 210.70.10.32 ~ 210.70.10.63IP를 가진 호스트로의 통신은 차단

        • 나머지 허용

      • 라우터 B를 기준 (Extended ACL 적용)

        • 210.70.30.9로 가는 FTP 트래픽은 차단

        • 210.70.10.0으로 가는 ping 트래픽 차단

        • 나머지 허용

      • 라우터 C를 기준 (Standard ACL 적용)

        • 210.70.20.224 ~ 239 트래픽을 차단

        • 나머지 허용

Access-list 설정.pkt


 9) Standard Access List와 Extended Access List의 차이점
    • Standard ACL은 출발지 주소(Source Address)만을 제어하는 반면, Extended ACL은 출발지 주소와 목적지 주소(Destination) 모두 제어할 수 있다.

    • Standard ACL은 전체 TCP/IP에 대한 제어만을 하는 반면, Extended ACL은 IP, TCP, UDP, ICMP 등 특정 프로토콜을 지정해서 제어 할 수 있다.

    • Standard ACL은 1 ~ 99까지의 숫자를 Access-list 번호로 사용하고, Extended ACL은 100 ~ 199까지의 숫자를 Access-list 번호로 사용한다.



  * 중요 TCP / UDP 포트 번호

Protocol

option 

port

Protocol 

option 

port

TCP

telnet

23

UDP

tftp

69

 

www(http)

80

 

 domain(dns)

53

 

ftp

21

 

 snmp

161

 

 smtp

25 

   

ICMP 

echo(ping)

7

 IP

 

 

 

 

 

 igrp

 

9


'학업' 카테고리의 다른 글

[컴퓨터네트워크설계] 7. 2계층 스위치 개요  (0) 2016.11.15
[File IO]  (0) 2016.10.24
[C Study] 함수  (0) 2016.10.01
스터디 OT  (0) 2016.09.21
[데이터베이스 설계 및 구축] 02. 데이터 베이스 개요  (0) 2016.09.08

함수(Function)

  1. 함수의 목적
    • 프로그래밍 시 값만 바뀔 뿐 같은 코드가 반복되는 경우
    • 함수(function)라는 기능을 통해 특정 용도의 코드들을 한 곳에 모아 처리
    • 예 ) printf, scanf
  2. 함수의 정의
  3. 반환값자료형 함수이름()
    {
     코드;
    }
  4. 함수의 호출
    • 함수는 main 함수 밖에서 작성해야 한다.
    // 반환값 없는 hello 함수 정의
    void hello() {
    	// Hello, World ! 출력
    	printf("Hello, World !\n");
    }
    
    main() {
    	// 함수의 호출
    	hello();
    }
    
  5. 함수의 실행
    1. main함수의 시작
    2. main함수 절차적 실행
    3. add 함수의 호출
    4. add 함수의 실행
    5. add 함수의 반환

  6. 함수의 선언
    • 사용자 정의 함수가 main 함수보다 아래에 있을 경우
main() {
	// 함수의 호출
	hello();
}

// 반환값 없는 hello 함수 정의
void hello() {
	// Hello, World ! 출력
	printf("Hello, World !\n");
}
    • C언어 컴파일러는 위에서 아래로 소스 코드를 해석하는데 main 함수 부분에서 hello 함수에 대한 정보가 없기 때문에 에러발생
    • 어떤 함수가 있다는 사실을 알려주려면 함수 선언(function declaration)을 해주어야 한다.


+ Recent posts