이래 저래 들려오는 정보들에 대한 의심의 쌓였습니다. 특히나 자신은 모든걸 잘 한다고 하시는 어떤 분

의 모든 말에 대해서 의심을 하게 됐습니다.

 며칠전 HTTP의 GET 과 POST 에 대해서 얘기를 하다가, POST 가 느린 이유에 대해서 알려 주는데,

이유는 POST 는 복호화를 거치기 때문이라고 합니다. 과연…궁금 합니다. 어떤 복호화를 하는 걸 까요?

말씀 후 자리를 황급히 떠나시는 그 분. get과 post ..궁금해 하던 중 아얘 TCP 에 대해서 잠깐 찾아 보던 중

아래와 같은 글을 찾아 볼 수 있었습니다. 부디 더더욱 자라나도록 하겠습니다.
===============================================================

TCP 자세히 보기

윤 상배

dreamyun@yahoo.co.kr

고친 과정
고침 0.8 2004년 5월 12일
Contro Bits 내용보강, sequence number 내용 보강, 이미지
수정

1. 소개

우리는 IP 자세히보기 를 통해서 IP 프로토콜을 헤더차원에서 살펴보았다. 이번 문서에서는 TCP 프로토콜을
헤더차원에서 살펴보도록 할것이다.


2. TCP (Transmission Control Protocol)

2.1. TCP 란

TCP 개념에 대해선 이미 몇개의 문서를 통해서 다루어지긴 했지만 확인차원에서 다시한번 다루어 보도록 하겠다.

TCP 는 기본적으로 IP 와 함께 사용되며, 그런이유로 TCP/IP 라고 불리워진다. IP는 호스트 사이의 데이타 교환을 목적으로
만들어진 프로토콜인데, 기본적으로 IP는 오로지 데이타 교환을 위한 임무만을 수행한다. 즉 네트웍상에서 발생할수 있는 데이타 누락, 패킷의 순서
뒤바뀜 등의 데이타 교정과 관련된 기능을 가지고 있지를 않다.

그래서 만들어 진개 TCP 프로토콜이다. IP 프로토콜의 상위 레벨 프로토콜로써, IP가 제공하지 못하는 기능즉, 데이타 누락검사 패킷순서
뒤바뀜 등 데이타 교정과 관련된 기능을 제공한다.

 +---+----+-------------+
|IPH|TCPH|Internet Data|
+---+----+-------------+

IPH : IP Header
TCPH : TCP Header
Internet Data : 교환하고자하는 데이타

이러한 TCP 의 기능상 특징으로 인하여 흔히 TCP 프로토콜을 “신뢰성있는
프로토콜” 이라고한다. TCP 는 이러한 신뢰성 있는 데이타 전송을 위한 방법으로 서버와 클라이언트간에 연결을 설정한다. 이러한 연결을 만드는
특성으로 TCP 프로토콜은 “연결지향 프로토콜” 이라고 말한다.

그림 1. 전 이중통신 선로

User inserted image

TCP 는 이러한
연결을 설정시 위에서의 그림에서와 같은 전 이중 통신 선로를 개설한다. 하나는 읽기 전용의 선로이며, 다른 하나는 쓰기 전용의 선로로써, 각각의
전용선로를 이용함으로 써 읽기와 쓰기를 동시에 할수 있게 된다. 이것은 Unix 에서 IPC 목적으로 pipe 를 생성할때, 읽기와 쓰기전용의
파이프를 동시에 생성하는것과 동일한 원리이다.

TCP 헤더에는 위의 TCP 의 특성을 충족시켜주기 위한 여러가지 기능을 가지는 필드들로 구성되어 있다. 우리는 다음장에서 TCP 헤더의
이러한 필드들을 분석함으로써, 어떻게 TCP 가 서버 클라이언트간 연결을 만들고, 신뢰성 있도록 데이타를 전달하는지 알아보게 될것이다.


2.2. TCP 헤더 구조

TCP 는 다음과 같은 헤더 구조를 가진다. 두 호스트 사이에 전송되는 TCP 데이타 단위를 세그먼트라고 부른다. 그러므로 TCP
세그먼트는 TCP 헤더 + DATA 가 될것이다. 다음은 TCP 세그먼트의 구조이다.

그림 2. TCP 헤더 구조

User inserted image


2.2.1. SOURCE PORT/DESTINATION PORT

source port 는 메시지를 보내는 측에서 통신을 위해 사용하는 port 번호이며, destination port 는 목적지, 즉
메시지를 받는측의 통신 port 번호이다.

여기에 있는 port 번호와 더불어 IP 헤더에 있는 source/destination address 를 이용하면 유일하게 식별되는
통신연결을 만들수 있게 된다.

아마도 IP 의 출발지/목적지 주소와 TCP 헤더의 출발지/목적지 포트 번호가 어플리케이션간 통신을 위한 가장 핵심이라고 할수 있을것이다.
다른 정보들은 통신을 원할하도록 도와주기 위해서 부가적으로 존재하는 것이라고 볼수 있다.

이들 포트번호의 크기는 16bit 크기를 가진다. 그러므로 대략 65536 만큼의 포트를 가질수 있을것이다.


2.2.2. SEQUENCE NUMBER

TCP 세그먼트안의 데이터의 송신 바이트 흐름의 위치를 가리킨다. 다른 호스트로 전달되는 패킷은 여러개의 서로 다른 경로를 거치면서
전달되다 보니 패킷의 순서가 뒤바뀔 수 있다. 이를 수신측에서는 재 조립해야할 필요가 있는데, Sequence Number 를 이용해서 조립하게
된다.


2.2.3. ACK

acknowledgment number 라고 말한다. 다음에 받을것으로 예상되는 데이타 옥텟의 순서번호를 나타낸다.


2.2.4. HLEN

TCP 세그먼트의 길이를 정의한다.


2.2.5. RESERVED

현재는 사용하지 않지만, 나중을 위해서 예약된 필드이다.


2.2.6. (Control)CODE BITS

세그먼트의 용도와 내용을 결정하기 위해서 사용된다. URG, ACK, PSH, RST, SYN, FIN 6개의 비트가 정의되어 있다.
TCP는 이러한 비트를 이용해서 패킷의 내용이 어떤 목적으로 전달될 것인지를 설정할 수 있다. 이들 비트중 SYN, ACK, RST를 주목할
필요가 있다.

SYN은 TCP연결을 만들 때, 양 호스간 sequence numbers의 동기화를 이루기 위한 목적으로 사용된다. ACK는 원격 호스트의
sequence number에 대한 응답을 위한 목적으로 사용된다. 즉 데이터를 잘 받았다는 걸 알려주기 위한 목적으로 사용되는데, 원격호스트의
sequence number의 번호에 +1을 해줘서 다시 전달하는 방법을 이용한다. SYN 비트는 특히 세번 악수 기법(three-way
handshake)를 위해서 사용된다.

RST 비트가 설정되어 있을 경우 받은 호스트는 즉시 연결을 끊어 버리고 FIN 비트가 설정되어 있을 경우 여러가지 테스트를 거쳐서 연결을
끊게 된다. 일반적인 정상종료를 원한다면 FIN 비트를 설정해서 사용하게 된다. 이들 비트에 대한 자세한 내용은 2.3.3절를 참고하기
바란다.


2.2.7. OPTION & PADDING

옵션은 말그대로 옵션이다. TCP 헤더의 정보를 좀더 확장시키고자 할때 사용한다. PADDING 은 32bit 크기를 채우기 위해서
사용된다.


2.2.8. CHECKSUM

TCP 세그먼트 데이타는 중간에 훼손될수 있으며, 변조될수도 있다. 그러므로 이를 체크할수 있는 장치가 필요하다. CHECKSUM 을
만드는 방법(알고리즘)은 기회가 되면 별도로 설명하도록 하겠다.


2.3. 실제 통신상에서 TCP 패킷의 내용을 살펴보자

위에서 각 TCP 필드에 대한 설명을 해보았지만, 솔직히 위의 정보만을 가지고는 뭐가 뭔지 도대체 알수가 없을 것이다. 그래서 이번에는
실제 TCP/IP 통신이 어떻게 이루어지는지에 대해서 알아보고 이러한 통신이 이루어지도록 어떻게 TCP/IP 패킷(세그먼트)가 전송되어지는지
알아보도록 하겠다.


2.3.1. 테스트 프로그램 준비

셈플로 알아보는 소켓프로그램 에서 제작한 적이 있는 우편번호 서버/클라이언트 프로그램을 이용해서 테스트 하도록
할것이다. 서버 프로그램의 이름은 zipcode 이며 클라이언트 프로그램의 이름은 zipcode_cl 이다.

이와 더불어 tcp/ip 패킷분석을 위해서 tcpdump 를 사용할것이니 준비해놓기 바란다. (아마도 기본 설치되어 있겠지만)


2.3.2. 테스트 방법

테스트를 가장 효과적으로 수행하기 위해서는 서버와 클라이언트가 별도의 네트웍에 묶여 있는게 가장 좋겠지만, 여의치 않을경우 하나의 서버에
서버와 클라이언트를 두고 테스트를 해도 관계 없다.

여기에서의 테스트는 서버와 클라이언트가 별도의 네트웍환경에 묶여있는 것을 기준하여 이루어질것이다.

그림 3. 서버/클라이언트 테스트 환경

User inserted image

Server 은 Port 번호 4445 로 연결하도록 할것이다.


2.3.3. 서버와 클라이언트간의 연결

TCP 는 기본적으로 연결지향의 프로토콜이라고 했다. 이말은 처음 통신을 하기 전에 서로를 연결하는 전용의 통신선로를 개설한다라는 말이
된다. 이는 우리가 전화를 할때

홍길동 : "여보세요 아무개 씨 맞습니까 ?"
아무개 : "내 아무개 입니다."
홍길동 : "아그러세요 저는 홍길동 입니다"
...
.... 이런 저런 대화들 ....
...

실제 대화를 하기 위해서 서로간에 확인절차를 거치는 것과 마찬가지다.

TCP 도 통신선로를 만들기 위해서 처음에 이러한 확인 절차를 거친다. 우리가 보통 전화상에서 서로의 확인 작업을 위해서 3번 통화가
이루어지는 것처럼 TCP 상에서도 3번의 데이타 전송이 일어난다.

                 client                                server

Send SYN seq=x ---------------------------> Receive SYN segment
|
② |
Recevie SYN+ACK segment <-------------------------- Send SYN seq=y, ACK x+1
|
| ③
send ACK y+1 --------------------------> Receive ACK segment

그런 이유로 흔히 위의 과정을 “3 way Hand Shaking” 또는 “3번
악수기법” 이라고 한다. 최초에 클라이언트가 seq 번호 x 를 보내면 server 에서는 이 x 에 1 을 더해서 ACK 로 보낸다. 이때
자신의 seq 번호 y 도 포함해서 보낸다. 그러면 클라이언트에서는 server 부터 넘어온 패킷의 ACK가 자신의 seq 번호와 일치하는지
확인하고, 확인이 되면 server 의 seq 번호인 y 에 1을 더해서 ACK로 보낸다. server 에서는 client 가 보낸 ACK 의
번호와 자신의 seq 번호가 일치하는지 확인해서 일치하면 연결이 제대로 되었다는것을 인증하고 데이타 통신에 들어가게 된다.

그럼 tcpdump 를 이용해서 어떻게 위의 3번 악수기법 이 이루어지는 지 확인해 보도록 하겠다. 우선 tcpdump 를 다음과 같은
옵션으로 띄우도록 한다.

   
[root@localhost test]# tcpdump -x tcp 4445
Kernel filter, protocol ALL, TURBO mode (575 frames), datagram packet socket
tcpdump: listening on all devices
...

그다음에 zipcode_cl 을 이용해서 서버에 접근해보자 그러면 아래와 같은
패킷 dump 화면이 뜰것이다. —– 1, —– 2 는 구분하기 쉽도록 필자가 추가시킨 문자이다.

   
13:42:47.952336 eth0 > localhost.2310 > 211.234.96.141.4445: S 2850317194:2850317194(0) win 5840 (DF)
4500 003c c1eb 4000 4006 1f2e c0a8 6482 ----- 1
d3ea 608d 0906 115d a9e4 638a 0000 0000
a002 16d0 0cc5 0000 0204 05b4 0402 080a
009c a261 0000 0000 0103 0300
13:42:48.202336 eth0 < 211.234.96.141.4445 > localhost.2310: S 2213490312:2213490312(0) ack 2850317195 win 5792 (DF)
4500 003c 0000 4000 3806 e919 d3ea 608d ----- 2
c0a8 6482 115d 0906 83ef 2e88 a9e4 638b
a012 16a0 cd8f 0000 0204 05b4 0402 080a
89be 031e 009c a261 0103 0300
13:42:48.202336 eth0 > localhost.2310 > 211.234.96.141.4445: . 1:1(0) ack 1 win 5840 (DF)
4500 0034 c1ec 4000 4006 1f35 c0a8 6482 ----- 3
d3ea 608d 0906 115d a9e4 638b 83ef 2e89
8010 16d0 fc0b 0000 0101 080a 009c a27a
89be 031e

3번 악수 기법을 위해서 3번의 패킷이 오고 갔음을 알수 있다. 언뜻 봤을때
절대 이해할수 없을것 같은 숫자로 된 정보들을 뿌려주는데 원리만 알면 간단하게 분석할수 있다. 위의 숫자로 된 정보들이 바로 TCP/IP
세그먼트의 정보를 16 진수로 나타낸 것이다. 4자리씩 구분되어 있는데, 이 4자리의 크기는 16 비트크기를 가진다(하나의 숫자는 4비트이다.
이 정보만 알고 있다면 위의 패킷정보에서 IP 영역과 TCP 영역을 분리해 낼수 있다.

IP 헤더의 크기는 유동적이긴 하지만 기본적으로 5 * (32 bit) 의 크기를 갖는다. 그러므로 —– 1 번 패킷을 높고 보자면
IP 헤더는 다음과 같을 것이다.

                         4500 003c c1eb 4000 4006 1f2e c0a8 6482  
d3ea 608d

정말 IP 헤더 정보가 맞는지 확인해보자. IP 헤더의 첫번째 4bit 는
IP의 버젼을 나타낸다. 위에서 보면 ‘4’ 로 되어 있음으로 이 TCP/IP 패킷은 IPv4 를 이용하고 있음을 알수 있다. c0a8 6482
는 source IP, d3ea 608d 는 destination IP 이다.

이제 —- 1 번 패킷에서 TCP 헤더 정보를 분석해 보도록 하자. 분석한 데이타는 tcpdump 헤더와 비교하면서 계산하도록 하자.
TCP 헤더데이타는 0906 부터이다. TCP 의 처음 16bit 는 SOURCE PORT 다음 16bit 는 DESTINATION PORT 를
나타낸다. 0906 을 계산해 보면(진수변환 되는 계산기로) 2310 이며 115d 를 계산해보면 4445 이다. 정확하게 일치하고 있음을 알수
있다. 클라이언트측의 PORT 번호는 서버측 포트 번호와는 달리 임의의 번호로 할당된다.

우리는 —- 1 번 패킷에서 a9e4 638a 가 시퀀스 넘버임을 유추해낼수 있을것이다. 이것을 계산해 보면 2850317194 임을
알수 있다. ACK는 0000 0000 이다. ACK 는 0000 0000 즉 0 으로 초기화 되어있는데 반해서, 시퀀스 넘버는 0으로 초기화
되어 있지 않다. 실지로 ACK 는 새로운 연결이 이루어질때 마다 0 으로 초기화 되는데 비해 시퀀스 넘버는 새로운 연결이 생길때 마다 임의의
번호로 새로 만들어진다.

Header Length 는 4bit 크기를 가지므로 a002 에서 ‘a’ 임을 알수 있다. 해서 Header Length 는 10(a) 임을 계산할수 있는데, 이때 Length 의 단위는 워드(32 bit) 이다. 그러므로 헤더는
0906 에서 0300 까지의 데이타임을 유추해 낼수 있다.

                                   0906 115d a9e4 638a 0000 0000
a002 16d0 0cc5 0000 0204 05b4 0402 080a
009c a261 0000 0000 0103 0300

즉 최초 세번 악수 기법을 통한 세션 연결시에 오고 가는 3개의 패킷 데이타는
단지 TCP/IP 헤더정보만을 포함하고 있으며, 그외의 아무런 다른 정보도 포함하고 있지 않음을 알수 있다.


2.3.3.1. 패킷 분석을 통해서 알아보는 3번 악수 기법 – 연결

이전에 —- 1 패킷을 분석함으로써, 우리는 dump 된 패킷을 분석하는 기본적인 기법을 배웠다. 이 방법들을 토대로 정말로 3번 악수
기법이 제대로 이루어 지는지 한번 확인해 보도록 하겠다.

3번 악수 기법을 보면 알겠지만 가장 핵심이 되는 키워드는 SEQ 번호와 ACK 번호 그리고 패킷의 타입을 나타내는 CODE BITS
이다. 이 세가지 필드의 의 계산만 잘하면 TCP 연결이 어떻게 이루어지는지 이해가 가능할것이다. 그럼 —- 1, —- 2, —-
3의 dump 패킷을 분석해서 3번 악수 기법의 흐름을 알아보도록 하자.

—- 1

클라이언트는 자신의 SEQ 를 a9e4 638a (2850317194)로 만들고 . ACK 를 0000 0000 (0) 으로 만들어서
—- 1 패킷을 서버측 측에 보낸다.

—- 2

서버는 클라이언트로 부터 —- 1 패킷을 받는다. SEQ 는 a9e4 638a 인데, 여기에 +1 (a9e4 638b) 를 해서 ACK
를 만든다. 그리고 자신의 SEQ 를 83ef 2e88 로 세팅해서 —- 2 패킷을 만들고 만들어진 패킷을 다시 클라이언트로 보낸다.

CODE BITS 를 보면 값이 02 임을 알수 있다. 2 는 2진수로 10 CODE BITS 의 세팅은 00 00 10 으로 되어있음을
알수 있다. 5번째 BIT 는 SYN 비트 임으로 이 패킷은 최초 연결을 시도하기 위한 패킷임을 알수 있다.

CODE BITS 를 보면 값이 12 임을 알수 있다. 이것을 2진수로 변경 시켜 보면 10 00 10 이다 그러므로 URG 와 SYN
비트가 세팅되어 있음을 알수 있다.

—- 3

클라이언트는 서버로 부터 —- 2 패킷을 받는다. —- 2 패킷에서 넘어온 ACK 를 확인해 본다. 최초에 클라이언트가 서버측으로
보낸 SEQ 에 +1 된 값이므로 올바른 데이타임을 확인할수 있다. 이제 —- 2 에서 넘어온 ACK 를 자신의 SEQ 로 설정하고,
—- 2 에서 넘어온 SEQ (83ef 2e88)에 +1 을 해서 —- 3 패킷을 만들고 이것을 서버로 보낸다.

CODE BITS 를 보면 값이 10 이다. 2진수로 10 00 00 임으로 URG 가 세팅되어 있음을 알수 있다.

이상 꽤 복잡한것 같지만 곰곰히 생각해 보면 별거 아니란걸 알수 있을것이다.


2.3.3.2. 패킷 분석을 통해서 알아보는 연결 종료

연결과는 좀 다르다. 완전한 종료를 위해서는 아래와 같이 4 번의 패킷 교환이 일어난다.

                 client                                server

Send SYN seq=x ---------------------------> Receive FIN segment
|
② |
Recevie segment <-------------------------- Send ACK x+1


Receive FIN + ACK segment <-------------------------- Send FIN seq=y, ACK x+1
|
| ②
Send ACK y + 1 --------------------------> Receive ACK segment

완전한 연결종료를 위해서 위의 zipcode 어플리케이션 대신에 telnet(port 23) 을 이용해서 테스트 하기로 했다. 테스트 방법은 telnet 로 해당 서버에 연결한
연결한 다음 login 프롬프트가 떨어지면 (CTRL + ]) 키를 이용해서 telnet> 프롬프트를 부르고 여기에 quit 를 입력해서
연결을 종료시키는 방법이다.

[root@coco test]# telnet 192.168.100.190
Trying 192.168.100.190...
Connected to 192.168.100.190.
Escape character is '^]'.


SunOS 5.8

login: // 여기에서 CTRL+] 입력
telnet> quit

이 과정을 tcpdump 로 패킷 덤프 받은 데이타 내용은 다음과 같다.

17:03:01.412336 eth0 > localhost.2437 > develop.telnet: F 110:110(0) ack 89 win 5840  (DF)
4500 0034 980c 4000 4006 5826 c0a8 6482 ---- 1
c0a8 64be 0985 0017 9d14 6d27 1f57 e476
8011 16d0 3621 0000 0101 080a 00ae f723
0444 cb7d
17:03:01.412336 eth0 < develop.telnet > localhost.2437: . 89:89(0) ack 111 win 10136 (DF)
4500 0034 23c2 4000 ff06 0d70 c0a8 64be ---- 2
c0a8 6482 0017 0985 1f57 e476 9d14 6d28
8010 2798 2302 0000 0101 080a 0444 cdd4
00ae f723

17:03:01.412336 eth0 < develop.telnet > localhost.2437: F 89:89(0) ack 111 win 10136 (DF)
4500 0034 23c3 4000 ff06 0d6f c0a8 64be ---- 3
c0a8 6482 0017 0985 1f57 e476 9d14 6d28
8011 2798 2300 0000 0101 080a 0444 cdd5
00ae f723
17:03:01.412336 eth0 > localhost.2437 > develop.telnet: . 111:111(0) ack 90 win 5840 < cdd5 0444 f723 00ae 080a 0101 0000 33c8 16d0 8010 e477 1f57 6d28 9d14 0017 0985 64be c0a8 4 ---- 6482 3132 ff06 4000 0034 4500 (DF) 71618005<>

패킷
분석방법은 위에서 모두 설명했으니 굳이 다시 설명하진 않겠다. 주의 해서 볼점은 CODE BITS 부분이다. —- 1 번을 보면 CODE
BITS 가 11 로 설정되어 있음을 볼수 있다. 이를 2진수로 변환하면 10 00 01 이다. FIN 비트 가 세팅되어 있음을 알수 있다.


2.3.3.3. 실 데이타 전송

실 데이타를 전송할때는 연결/종료 와 같은 3번 악수 기법에 의한 복잡한 (뭐 그리 복잡하지도 않지만) 그러한 패킷 교환은 없다. 단지
한쪽에서 데이타를 보내면 받은쪽에서는 데이타를 잘 받았다라는 패킷만을 보내게 된다.

이제 실제 데이타가 전송될때의 TCP/IP 패킷의 분석을 해보도록 하자. 여기에서는 다시 zipcode 의 서버/클라이언트가 사용될것이다.
zipcode_cl 을 이용해서 서버여 연결하고 “지역이름 입력 : ” 프롬프트가 떨어지면 a 를 입력해보도록 하자.

  
[root@s210-205-210-195 test]# ./zipcode_cl 4445
지역이름 입력 : a
지역이름 입력 :

다음은 위의 결과 를 tcpdump 를 이용해서 dump 뜬 결과 이다.

23:32:49.951938 s210-205-210-195.thrunet.ne.kr.33638 > 211.234.96.141.4445: P 1:256(255) ack 1 win 5840  (DF)
4500 0133 484f 4000 4006 176d d2cd d2c3 ---- 1
d3ea 608d 8366 115d 5b9e 5641 872e f2e8
8018 16d0 19eb 0000 0101 080a 0197 2287
89f5 edfc 6100 0000 5066 0140 0100 0000
dc81 0408 9460 0140 0f53 8e07 0f53 8e07
70f7
23:32:49.967321 211.234.96.141.4445 > s210-205-210-195.thrunet.ne.kr.33638: . ack 256 win 6432 (DF)
4500 0034 1f16 4000 3806 49a5 d3ea 608d ---- 2
d2cd d2c3 115d 8366 872e f2e8 5b9e 5740
8010 1920 214f 0000 0101 080a 89f5 f277
0197 2287
23:32:49.971577 211.234.96.141.4445 > s210-205-210-195.thrunet.ne.kr.33638: P 1:256(255) ack 256 win 6432 (DF)
4500 0133 1f17 4000 3806 48a5 d3ea 608d ---- 3
d2cd d2c3 115d 8366 872e f2e8 5b9e 5740
8018 1920 07d6 0000 0101 080a 89f5 f277
0197 2287 656e 6400 7365 6e64 2065 6e64
0a00 0000 0000 0000 0000 001c 9e04 0800
0000
23:32:49.971653 s210-205-210-195.thrunet.ne.kr.33638 > 211.234.96.141.4445: . ack 256 win 6432 (DF)
4500 0034 4850 4000 4006 186b d2cd d2c3 ---- 4
d3ea 608d 8366 115d 5b9e 5740 872e f3e7
8010 1920 204e 0000 0101 080a 0197 2289
89f5 f277

—- 1 에서 실제 데이타를 보내고 있으며 여기에서는 서버측으로 ‘a’ 를
보내게 될것이다. 실제 ‘a’ 를 보내는지 확인을 해보자. IP 헤더의 크기는 (5*32) 로 고정되어 있을것이다. 문제는 TCP 헤더의
크기인데, 8018 에서 8 이 헤더의 크기를 나타냄을 알수 있다. 단위는 워드 이므로 계산을 해보면(8 * 32) 8366 에서 부터 edfd
까지가 TCP 헤더 임을 알수 있다. 그러므로 우리가 보내고자 하는 데이타는 6100 에서 부터가 될것이다. 61 은 ‘a’ 라는걸 알수 있다.
– 61 은 10 진수 97 을 나타내며 ASCII 코드를 보면 97 은 ‘a’ 를 나타낸다.

서버에서 데이타를 받았다면 서버는 이에 대한 응답 메시지(저 메시지 잘 받았습니다) 를 클라이언트측에 보내야 할것이다. —- 2 패킷이
바로 응답 메시지가 된다. —- 2 패킷의 CODE BITS 를 보면 10 으로 세팅되어 있는데, 이것을 2진수로 변경하면 01 00 00
이 된다. 2번째 비트가 켜져 있는데 2번째 비트는 ACK 를 나타낸다. 그러므로 이 패킷은 응답용 패킷이라는 걸 알수 있다. 그렇다면 —
2 패킷을 받은 클라이언트는 이게 과연 —-2 패킷이 —- 1 에 대한 응답 메시지인지를 확인해야 하는데 이는 SEQ 번호와 ACK
번호를 계산함으로써 알나 낼수 있을것이다.

—- 3 번 데이타는 서버측에서 클라이언트로 보내는 패킷의 dump 내용이다. 클라이언트로 보내는 데이타는 “send end” 임을
알아낼수 있을 것이다. —- 4 번 데이타는 이에 대한 응답으로 클라이언트에서 서버측으로 보내는 패킷 dump 내용이다.


3. 결론

이상 TCP 헤더에 대한 비교적 상세한 내용을 다루었다. 이러한 내용들은 나중에 다루게될 RAW 소켓등 낮은 수준에서의 네트웍 프로그래밍을
원한다면 알아두어야할 내용이다. 또한 네트웍 관련 문제해결을 하는데 많은 도움을 줄것이다.

이 문서에서 이해되지 않는 내용등이 있다면 댓글을 달아주길 바란다. 그러면 최대한 공부를 해서라도 답변을 해주도록 하겠다.

샘플로 알아보는 소켓프로그램  

이문서에서 소켓의 모든것을 다루진 않겠다.(다룰수도 없다 –;) 소켓은 UNIX, INET, AX25, IPX, APPLETALK,
X25 등의 다양한 소켓패밀리와, 도메인을 지원할뿐만 아니라, 6가지 정도의 소켓타임을 가지고 있으며, 이에 대해서 제대로 설명하려면 책
몇권으로도 부족하다.
여기에서는 이 사이트의 취지에 맞도록 가장 간단하게 접근할수 있는 방법, 즉 “문고리”를 잡는데에 까지만을 설명하도록
하며, Unix(Linux) 상에서 가장 널리, 그리고 일반적으로 사용되는 INET(TCP/IP 를 이용한 인터넷 주소
패밀리)와 데이타 연결지향의 신뢰성이 높은 Stream(흔히 TCP 라고 하는) 에 대해서 다루도록 하겠다.

소켓 프로그램은 주로
서버-클라이언트 의 2개의 프로그램 쌍으로 이루어 진다. 서버는 서비스를 제공하는 프로그램이고 클라이언트는 서비스를 요청하는 프로그램이다.
FTP 를 예로 들자면, proftpd, wu-ftpd 등이 서버 프로그램이고, ncftp, cuteftp 등이 클라이언트
프로그램이다.
이러한 서버프로그램은 우리가 흔히 말하는 포트(port)에 대기 하며 클라이언트의 연결을 기다리고 (listen) 있다가,
클라이언트가 접근을 요청하면 이를 받아들여서(Accept) 서버-클라이언트 연결을 설정하고, 클라이언트의 여러 명령을 받아서 필요한 서비스를
하게 된다.
서버-클라이언트 환경을 만들기 위한 과정을 서버측에서 보자면 다음의 과정을 거치게 된다.

   
Socket 생성 -> Socket 에 이름연결 (bind)
-> 클라이언트의 연결을 기다림(listen)
-> 클라이언트를 받아들임 (Accept)
-> 클라이언트의 명령을 받아서 적절한 서비스를 수행

클라이언트측에서 서버에 접근하기 위해서는 단순히 소켓을 생성후 서버에
연결(connect) 하기만 하면 된다.

    Socket 생성 -> 서버에 연결 시도(connect) -> 서버에 각종 명령을 전달

C 를 통해서 서버 클라이언트를 프로그래밍하는 방법은 위의 내용들을 그대로 프로그램에
옮기는 과정이다.
그럼 실제로 소켓을 이용한 서버 클라이언트 프로그램을 만들어 보도록 하자.

일단 어떤 서비스를 제공하는
프로그램을 만들것인가를 정해아 한다. 우리가 만들 서버는 클라이언트에서 동이름을 입력하면 우편번호를 되돌려주는 우편번호 검색 프로그램이다.
우편번호는 파일로 저장되어 있으며, 클라이언트에서 지역 이름을 입력하면, 서버는 지역이름을 받아들이고, 파일을 라인단위로 읽어들여서 해당
지역이름을 포함하는 라인이 있는지 찾아서 이를 화면에 클라이언트측에 전달해주는 프로그램으로 quit 를 클라이언트측에서 보내면 프로그램을
끝내도록한다.(우편 번호를 저장한 파일은 대충 테스트용으로 하나 만들어서 사용하기 바란다)
여기에서는 한번에 하나의 클라이언트만을
받아들이는 단일서버 단일클라이언트 프로그램을 작성하도록 한다.
예제 프로그램들에는 여러가지 에러상황에 대한 코드를 생략하도록 하겠다.

그럼 먼저 서버 프로그램을 만들어 보도록 하겠다.

예제: zipcode.c

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{
int server_sockfd, client_sockfd;
int state, client_len;
int pid;

FILE *fp;
struct sockaddr_in clientaddr, serveraddr;

char buf[255];
char line[255];

if (argc != 2)
{
printf("Usage : ./zipcode [port]\n");
printf("예 : ./zipcode 4444\n");
exit(0);
}

memset(line, '0', 255);
state = 0;

// 주소 파일을 읽어들인다.
client_len = sizeof(clientaddr);
if((fp = fopen("zipcode.txt", "r")) == NULL)
{
perror("file open error : ");
exit(0);
}

// internet 기반의 소켓 생성 (INET)
if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket error : ");
exit(0);
}
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(atoi(argv[1]));

state = bind(server_sockfd , (struct sockaddr *)&serveraddr,
sizeof(serveraddr));
if (state == -1)
{
perror("bind error : ");
exit(0);
}

state = listen(server_sockfd, 5);
if (state == -1)
{
perror("listen error : ");
exit(0);
}

while(1)
{
client_sockfd = accept(server_sockfd, (struct sockaddr *)&clientaddr,
&client_len);
if (client_sockfd == -1)
{
perror("Accept error : ");
exit(0);
}
while(1)
{
rewind(fp);
memset(buf, '0', 255);
if (read(client_sockfd, buf, 255) <= 0)
{
close(client_sockfd);
break;
}

if (strncmp(buf, "quit",4) == 0)
{
write(client_sockfd, "bye bye", 8);
close(client_sockfd);
break;
}

while(fgets(line,255,fp) != NULL)
{
if (strstr(line, buf) != NULL)
{
write(client_sockfd, line, 255);
}
memset(line, '0', 255);
}
write(client_sockfd, "end", 255);
printf("send end\n");
}
}
close(client_sockfd);
}

서버 프로그램은 클라이언트의 연결을 기다린다음, 연결이 만들어지면 클라이언트로 부터
검색을 원하는 지역이름을 입력받는다. 지역이름을 입력받으면, 각 지역이름과 우편번호가 저장되어 있는 파일의 내용을 읽어들여서, 지역이름 포함한
라인을 클라이언트측에 전송하게 된다. 만약 클라이언트로 t” 문자열을 입력받으면 연결을 끊게 된다.
가장 먼저 소켓을 생성해야 하는데 이는
socket(2) 함수를 이용하게 된다. 여기에는 3개의 매개 변수가 전달되는데, 각각 통신 도메인의 종류,
통신타입, 사용할 프로토콜을 지원하게 된다. 일반적인 인터넷 어플리케이션의경우 도메인종류로 AF_INET, 그리고 연결지향의 신뢰성 있는 통신을
위해서 SOCK_STREAM 타입을 사용한다.
프로토콜은 특별히 지정된게 없으며, 그냥 0을 사용하도록 한다.
socket 를
만들었으면 통신 환경에 맞게, sockaddr_in 구조체를 체워주게 된다. 이 구조체의 내용은 다음과 같다.

           
struct in_addr
{
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
}

sin_family 는 소켓타입이며, sin_port 는 연결에 사용되는 port
번호이고, sin_addr 은 연결을 받아들일 IP 어드레스이다. 예제에서는 INADDR_ANY 를 사용했는데, 이는 모든 IP에 대해서 연결을
받아들이라는 뜻이다. socket() 이용해서 만든 소켓에 이름을 할당하여 실지로 어플리케이션이 사용가능한 상태로 만들어 줘야 하는데
이를 “소켓에 이름을 할당한다” 라고 하며 bind(2) 함수를 이용해서 구현한다.
그다음에 listen(2)를 이용해서 연결을 기다리고, accetp(2) 를 이용해서 연결을 받게 된다. accept 를 이용해서 연결이 완성되면 accept 는
소켓과 연결되는 “파일 지시자”를 돌려주고 이 “파일 지시자” 를 통해서 클라이언트와 서버간의 메시지를 주고 받게 된다.
일단 연결이
이루어진다음에 서버가 하는일은 간단하다. 클라이언트의 문자열을 읽어들이고(지역이름), 파일에서 이 지역을 포함한 주소가 있는지 확인해서, 이를
클라이언트측에 전송해주면 된다. 주소검색이 모두 끝났다면 “end” 문자열을 클라이언트에 돌려줌으로써, 모든 검색이 끝났음을 클라이언트에게
알려준다.
클라이언트측에서 “quit” 문자열을 보내기 전까지 이 프로그램은 계속해서 클라이언트와 연결해서 업무를 수행한다.
“quit”문자열을 받게 되면, close(2) 를 이용해서 클라이언트와의 연결을 끊고, 새로운 클라이언트를 받아들일 준비를 하게 된다.

이제 클라이언트 예제이다.
에제: zipcode_cli.c

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{

int client_len;
int client_sockfd;

FILE *fp_in;
char buf_in[255];
char buf_get[255];

struct sockaddr_in clientaddr;

if (argc != 2)
{
printf("Usage : ./zipcode_cl [port]\n");
printf("예 : ./zipcode_cl 4444\n");
exit(0);
}


client_sockfd = socket(AF_INET, SOCK_STREAM, 0);
clientaddr.sin_family = AF_INET;
clientaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
clientaddr.sin_port = htons(atoi(argv[1]));

client_len = sizeof(clientaddr);

if (connect(client_sockfd, (struct sockaddr *)&clientaddr, client_len) < 0)
{
perror("Connect error: ");
exit(0);
}
while(1)
{
printf("지역이름 입력 : ");
fgets(buf_in, 255,stdin);

buf_in[strlen(buf_in) - 1] = '\0';
write(client_sockfd, buf_in, 255);
if (strncmp(buf_in, "quit", 4) == 0)
{
close(client_sockfd);
exit(0);
}
while(1)
{
read(client_sockfd, buf_get, 255);
if (strncmp(buf_get, "end", 3) == 0)
break;

printf("%s", buf_get);
}
}

close(client_sockfd);
exit(0);
}

클라이언트는 서버에 비해서 좀더 간단하다.
sockaddr_in 구조체만
설정하고 해당 서버에 연결(connect(20) 하는걸로 서버연결을 마칠수가 있다.
연결이 만들어 지고 나면, fgets() 를 이용해서 사용자의 표준입력 문자열을 입력받게 된다. 인력받은 문자열은 write() 를 통해서 서버에 전달되며, read 를 이용해서 서버측에서의 검색결과를 읽어온다. 검색결과는
서버측에서 검색결과를 마쳤을시 전송되는 “end”를 만나기 전까지 계속 해서 읽어오게 된다.
실행화면

[yundream@localhost test]# ./zipcode 4444&
[2] 9675
[yundream@localhost test]# ./zipcode_cl 4444
지역이름 입력 : 역삼
서울시 강남구 역삼동:100-500
지역이름 입력 : 강남구
서울시 강남구 역삼동:100-500
서울시 강남구 삼성동:108-508
지역이름 입력 : quit
[yundream@localhost test]#

이상 간단하게 나마 “소켓”을 이용한 서버-클라이언트 의 기초적인 내용을
알아보았습니다. 도움이 되었는지 모르겟군요. 다음번에는 파일기반의 소켓을 이용한 내부 프로세스의 통신(AF_UNIX)의 방법을 예제를 통해서
알아보도록 하겠습니다.
좀더 좋은 내용을 준비하도록 최선의 노력을(–;) 다하겠습니다. 그럼 좋은 하루 되세요..

network 장비로 알아보는 OSI계층구조

윤 상배

dreamyun@yahoo.co.kr

교정 과정
교정 0.8 2003년 4월 14일 21시
최초 문서작성


1절. 소개

우리주변엔 많은 네트워크장비가 있다. 이들 장비는 매일매일 접하는 것에서 부터 지금은 거의 사용하지 않는 장비들까지 다양하게 존재한다.

아마도 당신은 네트워크상에서 장비개발 혹은 소프트웨어의 개발을 위해서 OSI7참조계층을 따른다는 것을 알고 있을것이다. 이번 글에서는
몇가지 중요한 네트워크장비들에 대한 개요와, 이들장비가 OSI의 각 계층과 어떠한 연관성을 가지면서 작동하는지에 대해서 알아보도록 하겠다.

물론 이글을 제대로 이해하기 위해서는 최소한 아래의 그림정도는 이해하고 있어야 할것이다.

그림 1. OSI7계층

User inserted image

OSI7계층에 대한
자세한 설명은 이 사이트의 다른 문서들을 참고하기 바란다. 위의 그림에서 가장 밑바닥이 7로 되어있어서 혼동될수 있는데 가장 밑층이 계층 1(layer 1)이 된다.

보통의 네트워크 장비들은 하드웨어장비들로 소프트웨어와는 별상관없음으로 위의 7계층중에서 4계층인 Transport계층까지를 다루게 된다.
이 글역시 OSI7계층중 4계층까지를 다루게 될것이다.


2절. 리피터(repeater)

LAN영역에서 다른 LAN영역을 서로 연결하기 위한 목적으로 사용된다.

지금은 네트워크상에서 오고가는 데이타가 많아서, 어떻게 하면 하나의 LAN영역을 좀더 효율적으로 나눌수 있느냐가 중요한 과제이지만 과거에는
어떻게 하면 분리되어있는 LAN영역을 하나의 LAN영역으로 통합할수 있느냐가 주된 과제이자 관심사였다.

과거에는 부서가 층이 나늬어져 있고, 각각의 LAN세그먼트들로 이루어져 있을경우 원할한 데이타 소통을 위해서 2개로 나뉘어진
LAN세그먼트들을 하나로 묶기위한 작업이 자주 발생했었다. 그러나 지금은 같은 층의 같은 부서에서 조차도 세그먼트를 나누려고 하는 경우가 대부분
이다.

이처럼 2개의 LAN세그먼트를 하나의 LAN세그먼트로 통합하고자 할때 발생하는 문제는 데이타가 전달되어야 하는 망이 길어진다는 점이다.
망을 가로지르면서 데이타를 전송하는 매체는 전자기신호가 된다. 이 전자기 신호는 매체(구리선)을 타고 이동하면서 에너지를 잃고 신호가 감쇠되게
된다. 혹은 여러가지 잡음이 생겨날수도 있다. 이러한 신호감쇠와 잡음은 당연히 통과하고자하는 매체의 길이가 길어 질수록 심하게 일어나게 된다.

그럼으로 2개의 LAN세그먼트를 연결하고자 할때는 이러한 신호감쇠와 잡음을 처리하기 위한 장치를 필요로 하게 된다. 이러한 일을 해주는
네트워크 세그먼트간 연결장치가 바로 리피터이다.

리피터는 OSI계층과는 아무런 상관이 없다. OSI계층에 포함된 어떤 프로토콜을 다루는 장치가 아닌 단지 신호를 증폭하고 잡음을 없애는
장치이기 때문이다.

작은 정보: 잡음을 없애지 않고 단순히 증폭만 하는걸 앰플리파이어(Amplifier) 혹은 증폭기라고 한다. 오디오기기에도
널리 쓰인다. 보통 오디오기기에서 앰프를 써서 사운드를 증폭시킬경우 잡음까지 함께 증폭되는걸 경험해보았을것이다. 하긴 요즘엔 잡음제거 기능까지
있는 앰플리파이어가 사용되기도 한다.

지금은 거의 사용되어지지 않는 장비다.


3절. 허브(hub)

hub의 사전적인 뜻은 “중심”,”중추”이다. 흔히 볼수 있는 자전거 바퀴살이 모인 중심부분을 허브라고 한다. 자전거에서 허브가 하는일은
바퀴살에 의해서 전달되는 힘을 중심으로 모으고 이를 다시 바퀴살에 골고루 분산시켜서 힘을 균일하게 받도록 하는 일이다.

우리가 관심을 가지고 있는 네트웍장비로써의 허브역시 자전거에서의 허브와 같은일을 한다. 자전거에서의 허브가 여러개의 바퀴살에 힘을 균등하게
나누기 위한 게 주 목적이였다면, 네트웍장비에서의 허브는 통신을 위해 물려있는 여러개의 호스트가 모두 통신을 할수 있도록 통신의 중심축이 되는게
주목적이다.

보통 하나의 지역 네트워크를 여러개의 호스트가 공유해서 사용하기 위한목적으로(여러개의 세그먼트로 분리하기위한) 널리 쓰이고 있다. 허브는
크게 2가지 종류가 있다.


3.1절. 더미 허브(dumy hub)

그림 2. 단순 무식한 더미 허브

User inserted image

허브 본래의 목적에
충실한 허브이다. 위의 그림을 보면서 설명을 하겠다. A호스트가 B호스트에게 메시지를 보내고자 할때, 메시지는 허브로 전달되고, 허브는 B,
C, D 각 호스트 모두에게 메시지를 전달 한다. 데이가 자신에게 전달된건지 그렇지 않은건지는 B, C, D 각 호스트의 몫이다. 이들 호스트는
받은 패킷이 자신에게 보내어진 패킷인지를 판단하게 된다. 만일 자신에게 보내어진 패킷이 아니라면 이 패킷은 버려지게 되고, 그렇지 않을경우
최종적으로 애플리케이션 계층까지 전달되게 될것이다.

더미허브는 구현이 간단하고 쉽게 사용할수 있고, 때문에 가격이 싸다는 장점을 가지고 있지만, 2가지 정도의 단점을 가진다.

첫번째 문제가 통신보안 문제다. 모든 호스트로 패키지가 전달된다는게 문제인데, 때문에 같은 LAN에 묶여있는 어떤 호스트의 패킷이라도
도청가능해지기 때문이다.

두번째 문제는 통신효율의 문제이다. 더미 허브의 경우 모든 호스트를 단일 세그먼트로 묶어버린다. 네트워크쪽을 공부해봤다면 알겠지만, 하나의
세그먼트 상에서는 오직 한번에 하나의 호스트만 데이타를 보낼수 있다. 이유는 동시에 2개의 호스트가 어떤 데이타를 보내게 될경우
충돌(collision)이 발생하기 때문이다. 이것은 노래방에서 노래를 부르기 위해서 마이크를 돌리는것과 유사하다. 마이크는 한번에 한명만이
가질수 있고, 때문에 사람이 많으면 많아질 수록 노래부르기는 점점힘들어 질것이다. 마찬가지로 호스트가 많으면 많아질수록 그리고 보내고자 하는
데이타가 많아 질수록 LAN에서이 효율은 극도로 떨어지게 될것이다.

리피터와 마찬가지로 단지 패킷을 복사해서 전달하는 일만을 하는 장치임으로 OSI계층과는 무관하게 작동한다.


3.2절. 스위칭 허브(switching hub)

위에서 설명했듯이 더미 허브의 가장큰 문제는 LAN을 하나의 세그먼트로 묶어버린다는 점이다.

이 문제를 해결한게 스위칭 허브이다. 스위칭 허브는 세그먼트를 여러개로 나누어준다. A호스트에서
B호스트로 패킷을 보내려고 할때, 더미허브는 모든 호스트에 패킷을 복사해서 보냈지만, 스위칭 허브는 B호스트에게만 패킷을 보낸다.

그림 3. 세그먼트를 나누어서 관리하는 스위칭 허브

User inserted image

스위칭 허브라는 이름처럼 이 장치는 패킷을 해당 세그먼트로 스위칭 시켜준다.

그런데 해당 호스트로 패킷을 스위칭하기 위해서는 패킷이 어디로 향하고 있는지에 대한 정보를 허브가 알고 있어야만 할것이다. 스위칭 허브는
MAC주소를 이용해서 어느 세그먼트로 패킷을 보내야할지를 결정할수 있다.

작은 정보: Media Access Control의 줄임말이다. 이더넷장치에 할당되는 유일한 번호이다. 6byte(48)비트의 크기를 가진다. MAC 어드레스는 OSI 2계층에서 사용된다.

MAC주소는 유일해야 하기 때문에 IEEE에서 어드레스 할당을 관리하고 있다.

MAC어드레스는
데이타링크 계층(Layer 2)에서 사용되어진다. 이런이유로 L2 스위치라고 부르기도 한다. L3, L4스위칭 허브역시 존재한다. 위로
올라갈수록 로드밸런싱등의 부가적인 기능을 제공해주긴 하지만 그만큼 가격을 지불해야 한다.


4절. 브릿지(bridge)

브릿지의 뜻을 찾아보면, “다리”, “교량”, “이어주는” 이라는 뜻을 가진다. 때문에 보통 브릿지라함은 2개의 네트워크영역을
묶어주는것으로 생각할수 도 있는데, (굳이 틀렷다고 할수없긴 하지만) 이것은 잘못된 생각이다. 브릿지는 하나의 네트워크 세그먼트를 2개이상으로
나누어서관리하기 위해서 만들어진 장비이다. 하나로 통합해서 관리하기 위한 허브와 비교될 수 있다.

하나의 네트워크영역을 2개이상으로 나누어야할 필요는 자주 발생한다. “가”라는 연구부서가 있다고 가정해 보자. 이 연구부서의 지역네트워크는
A에서 F, 6대의 호스트로 이루어져 있다. 이중 A, B, C 호스트는 내부 연구용호스트로 다량의 패킷을 발생시키는 매우 시끄러운
호스트들이다. 같은 네트워크 세그먼트에서 한쪽이 시끄러우면 이것은 전체 지역네트워크에 영향을 미친다. 그럼으로 시끄러운 호스트와 그렇지 않은
호스트를 분리 시켜야할 필요가 있다.

간단히 생각해서 방하나에 시끄러운 팀과 그렇지 않은 팀을 섞어 놓으면, 서로 방해가 될수 있음으로 이들 두팀을 분리하기 위해서 칸막이를
치는것과 같은 거라고 생각하면 된다.

브릿지가 바로 이 칸막이의 역활을 한다. 브릿지를 이용해서 하나의 지역 네트워크를 시끄러운 A,B,C호스트와 그렇지 않은 D,E,F
호스트가 서로방해 받지 않고 사용할수 있는 2개의 세그먼트로 분리시킬수 있다. 아래의 그림은 브릿지를 이용해서 2개의 네트워크 세그먼트로 분리된
“가”연구소의 네트워크 환경이다.

그림 4. 브릿지를 통해서 나누어진 지역네트워크

User inserted image

작동방식은 간단하다. A에서 B혹은 C로 가는 패킷은 D,E,F에는 전달되지 않고, 브릿지를 통해서 B와 C로만 패킷이 전달되도록 하는
것이다. 이러한 작동을 위해서 브릿지는 이더넷장치에 유일하게 부여되어 있는 MAC어드레스를 이용한다.

브릿지는 각 MAC주소를 이용해서 브릿지테이블을 작성한다. 이 테이블에는 각 목적지 MAC이 어느 세그먼트에 포함되어 있는지에 대한 정보를
포함하고 있다. “가” 연구부서에 대한 브릿지 테이블은 다음과 같은 형식으로 작성될 수 있을것이다.

표 1. Bridging Table

호스트 이름 호스트 MAC 주소 네트워크 세그먼트
A 11 1
B 28 1
C 17
D 19 2
E 20 2
F 9 2

만약 A호스트에서 C호스트로 어떤
데이타를 보내고자 한다면, 이 데이타는 B, C호스트와 브릿지로 전달될것이다. B와 C호스트는 받은 패킷을 적당히 처리할것이다(B는 버리고 C는
처리한다). 브릿지에서는 해당 데이타 패킷의 출발지 MAC주소와 도착지 MAC주소를 확인하고 동일한 세그먼트 1로 향하는 패킷임을 알아내게
될것이다. 브릿지는 이 패킷을 버리게 된다.

A호스트에서 D호스트로 어떤 데이타를 보내고자 한다면, 역시 이데이타는 B, C, 브릿지로 전달될것이다. 브릿지에서는 브릿징 테이블을
확인해서 다른 세그먼트 2로 전달되는 패킷이라는걸 알아내고 세그먼트2로 패킷을 전달할것이다.

이런식으로 세그먼트 1의 호스트들끼리 다량의 패킷을 발생시킨다고 하더라도 세그먼트 2의 네트워크 환경에 영향을 미치지 않게 된다.

브릿징 테이블을 만들기 위해서 사용되는 프로토콜은 STP(spanning Tree Protocol)로 다중의 브릿지로 구분되어있는 네트웍환경에서 효과적으로
네트워크 토폴로지를 구성/변경 할수 있도록 도와준다. 주로 중소규모의 네트워크환경에서 사용된다. 이 프로토콜은 MAC주소 기반이다. MAC주소를
다루는 OSI레이어는 2계층인 데이타 링크계층임으로, 브릿지는 L2기반 장비로 분류할수 있을것이다.


5절. 라우터

리피터와 브릿지, 허브가 비교적 근거리에서 네트워크(LAN)를 통합하거나 분리하기 위해서 사용하는 반면, 라우터는 원거리에서 네트워크간
통합을 위해서(네트워크의 네트워크) 사용되는 장비이다.

특히 라우터는 인터넷 세계에서는 없어서는 안될 중요한 장비로 실제 인터넷이 존재가능 하도록 만들어주는 장비이다.

라우터를 이용해서 거미줄 처럼 얽혀있는 인터넷상에서 원하는 목적지로 데이타를 보낼수 있으며, 원하는 곳의 데이타를 가져올수도 있다.

그렇다면 어떻게 라우터를 통해서 데이타를 목적지까지 보낼수 있는지에 대해서 간단히 알아보도록 하겠다. 이 내용은 이미 이 사이트에서 몇번
다루어본적이 있음으로 정리하는 마음으로 읽어내려가기 바란다.

인터넷은 네트워크의 네트워크임으로 결국에는 수많은 라우터들을 이용해서 이들 네트워크간을 묶어줘야 할것이다. 그래서 우리가 미국의 특정
호스트로 데이타를 보내고자 한다면, 때에 따라서는 수십개의 라우터를 거쳐야할 경우도 생길것이다. 어쨋든 아주 가까운 거리에 있는 호스트를
찾아간다고 하더라도 최소한 3-4개 정도의 라우터는 거쳐야 한다.

각각의 라우터는 들어온 패킷이 주위에 있는 여러대의 라우터중 어느 라우터로 패킷을 보내야할런지를 결정할수 있어야만 한다. 모든 제대로된
결정을 위해서는 데이타와 정보가 필요하다. 라우터의 입장에서 데이타는 패킷에 적혀있는 목적지 주소(IP)이며 정보는 라우팅 테이블이 된다.

라우팅 테이블은 진정으로 라우터가 라우터로써의 기능을 가능하도록 만드는 핵심정보를 가지고 있다. 즉 패키지가 목적지 주소로 올바르게
전달되기 위해서는 어느 인터페이스를 통해서 다음 라우터로 전달되어야 하는지에 대한 정보를 가지고 있는데 라우팅 테이블이다.

표 2. Bridging Table

목적지 주소 마스크 인터페이스
211.109.3.0 255.255.255.0 eth0
211.109.4.0 255.255.255.0 eth1
211.108.0.0 255.255.0.0 eth2

라우팅 테이블의 구조는 위에서
처럼 간단하다. 목적지IP를 가지는 패킷이 어느 인터페이스를 사용하면 되는지에 대한 정보를 가진다. 만약 패킷이 들어왔는데, 패킷의 IP헤더에
포함된 목적지 주소가 211.109.3.1에서 211.109.3.254 사이의 값을 가진다면 라면 라우팅 테이블의 정보에 의해서 인터페이스
eth0으로 보내어질 것이다.

이러한 라우팅 테이블은 RIP이라는 프로토콜을 이용해서 네트워크 환경변화에 적응하여 변할수 있도록 되어 있다. RIP을 이용한
라우팅테이블의 동적인 변화에 대해서는 TCP/IP 개요(2)를 참고하기 바란다.

이상으로 라우터는 기본적으로 네트워크 계층(Layer 3) 장비임을 알수 있을것이다.

라우터는 소프트웨어만으로 충분히 구현가능하다. 리눅스를 이용해서 라우터를 만드는 프로젝트도 있는데, 관심있다면 리눅스 라우터 프로젝트를 방문해보기 바란다.

IP (Internet Protocol)

윤 상배

dreamyun@yahoo.co.kr

교정 과정
교정 0.8 2003년 3월 19일 23시
이미지추가

차례
1절. 소개
2절. IP (Internet Protocol)
2.1절. IP 란
2.2절. IP 헤더
2.3절. 경로배정(routing)
2.4절. 데이타 단편화 (fragmentation)
2.4.1절. MTU(Maximum Transmission Unit)
2.4.2절. 단편화및 재조립
2.5절. IP 헤더의 예
3절. 결론


1절. 소개

우리는 그동안 몇번의 기사를 통해서 IP에 대해서 이미 알아보았다. 이번에는 IP에 대한 좀더 자세한 내용을 알아보도록 하겠다.

이문서는 여러분이 TCP/IP 에 대한 기본적인 이해를 하고 있다고 가정할것이다. 이 문서를 읽기전에 TCP/IP 개요, TCP/IP 개요(2), TCP/IP 개요(3) 에 대한 문서를 먼저 읽어서 TCP/IP 에 대한 어느 정도의 이해를 해놓길
바란다.


2절. IP (Internet Protocol)

2.1절. IP 란

IP 는 인터넷으로 연결된 호스트 사이에 bit 패키지(인터넷 데이타 그램)의 교환을 가능하도록 하기 위해 만들어진 프로토콜이다. IP는
인터넷 환경에서 host 간 데이타 그램의 교환을 목적으로 하므로 host-to-host 프로토콜이라고 불리우기도 한다.

IP는 addressing(주소지정) 과 데이타 그램의 단편화를 통해서 데이타 그램을 교환한다. 일단 보내고자 하는 크기의 데이타가
있다면, IP는 이 데이타를 한꺼번에 보내지 않고, 여러개의 조그만 데이타 그램으로 단편화 (fragmentation) 작업을 수행하게 된다.
그리고 이러한 단편화된 데이타 앞에 목적지로 찾아갈수 있도록 하기 위한 여러가지 정보 들을 채워 넣게 된다(이것을 IP Header 이라고
한다).

그림 1. 단편화된 데이타들

User inserted image

위의 그림을 보면
하나의 Internet Data 를 보내기 위해서 3개의 조그만 데이타로 쪼개고 이앞에 IP Header 을 붙였음을 알수 있다.

IP 프로토콜은 다음과 같은 몇가지 특징을 가지고 있다.

비신뢰성(unreliable)

IP 는 데이타 그램이 목적지로 전달될 것이라는 것을 보증하지 않는다. IP 데이타 그램은 목적지로 가는 도중 여러가지 원인에 의해서
손실될수도 있는데, IP 헤더에는 이러한 손실을 복구하기 위한 어떠한 장치도 마련되어 있지 않다. 대신에 TCP 에 이러한 데이타 손실을
복구하기 위한 장치를 마련한다.

비연결지향성(connectionless)

호스트와 호스트간에 데이타 그램을 전달하기 위하여서 세션을 개설하지 않는다. 모든 데이타 그램은 각각 독립적으로 전달되게 된다. 받는
호스트에서는 해당 데이타 그램간의 연관성에 대해서 전혀 알지 못한다. 만약 A와 B 데이타가 호스트로 전달되고, A가 첫번째 데이타 B가 두번째
데이타라고 한다면, 받은측에서는 어느 데이타가 첫번째 데이타인지 알지 못한다. 또한 B데이타가 A데이타 보다 먼저 전달될수도 있는데, IP는
이를 교정할수 있는 장치를 가지지 않는다.


2.2절. IP 헤더

이번장에서는 IP 프로토콜의 헤더 포맷에 대해서 알아보도록하겠다.

그림 2. IP 헤더

User inserted image

Version: 4bits

IP 포맷의 버젼을 나타낸다. 현재는 주로 IPv4 가 가장 널리 쓰이며, 차세대 포맷으로 IPv6 가 제안되어서 조금씩 사용범위가
늘어나고 있는 추세이다.

IHL(Internet Header Length): 4bits

IP 헤더의 길이다. 보통은 32bit 크기를 가지는 5개의 열로 이루어진다. 나마지 하나의 열은(Options, Padding)는
옵션사항이다.

Type of Service: 8 bits

인터넷에는 다양한 종류의 데이타 그램이 돌아다닌다. 이중 어떤것은 상대적으로 중요한 데이터 그램이라서 데이타 전송에 있어서 다른 데이타
그램보다 전송에 있어서 우선순위를 두어야 하는 그런경우가 있을것이다. 이럴때 Type of Service 를 이용함으로써, 데이타 그램의 전송에
대한 우선순위 등을 제어할수 있다. 간단한 형태의 QOS(Quality of service) 라고 볼수 있다.

Total Length: 16 bits

IP 헤더와 실제 데이타의 크기를 모두 합친 크기이다.

Identification: 16 bits

보내고자 하는 데이타 그램에 단편화(fragmentation)가 일어났을경우 단편화된 각 데이타 그램을 구분할수 있는 일련의 번호이다. 이
값을 이용해서 이 데이타 그램이 어떤 데이타 그램에서 단편화 된것인지를 알수 있다.

Flags: 3bits

데이타 그램의 단편화에 대한 정보를 알려주기 위해서 사용된다. 첫번째 비트는 예비로 사용되며, 0으로 세팅된다. 두번째 비트와 세번째
비트는 단편화된 데이타그램의 정보를 세팅하기 위해서 사용된다. 두번째 비트가 0으로 세팅되었을경우 단편화된 데이타임을 의미하며, 1일경우 단편화
되지 않은 데이타를 의미한다. 3번째 비트가 0일경우 마지막 단편화 데이타 임을 나타내며, 1일경우에는 단편화된 데이타가 더 있다는것 나타낸다.

표 1. Flags 세팅

0 예비 : 반드시 0
1 (DF) 0 = 단편화되었음, 1 = 단편화되지 않았음
2 (MF) 0 = 마지막 단편화 데이타, 1 = 단편화 데이타 더
있음
     0   1   2
+---+---+---+
| | D | M |
| 0 | F | F |
+---+---+---+
Fragment Offset: 13bits

데이타그램에 대한 단편화가 일어났을경우 현재 데이타 그램이 원래 데이타 그램의 몇번째 위치부터 단편화가 이루어 졌는지를 나타낸다.

Time To Live: 8bits

흔히 TTL 이라고 불리우는 값으로 데이타 그램이 살아있을 시간을 지정한다. 시간 이라고 해서 1시간 2시간 하는 시간이 아닌, 몇개의
라우터를 이동할수 있는지를 명시함으로써 데이타 그램의 생존기간을 명시한다. IP 데이타 그램이 라우터를 경유하게 되면 라우터는 TTL 필드를
조사해서 TTL의 값에 1을 빼준다. 만약 TTL 에 16의 값이 세팅되어 있다면 16번째 라우터를 지날때 TTL 값은 0이 될것이며, 라우터는
이 데이타 그램을 전달하지 않고 drop 시켜버린다. TTL 값을 명시하는 이유는 데이타 그램이 라우터 상에서 무한 순환 하는 사태가 발생할수
있기 때문이다.

Header Checksum: 16bits

Header 정보는 고정된게 아니고 필요에 따라 바뀌게 된다(TTL 과 같은정보). 그러므로 헤더를 체크할수 있는 장치를 필요로 한다.

Source Address: 32bits

데이타그램을 보내는 측의 IP 주소이다.

Destination Address: 32bits

데이타그램을 받는측의 IP 주소이다.

Options: 크기변화

프로그램의 특성에 의해서 특정한 기능을 추가하기 위해서 사용된다. 이 필드는 필수적인 것이 아니다. 데이타 그램에 보안기능을 추가하거나,
QOS 와 같은 기능, 혹은 라우팅관련된 부가적인 여러 기능을 추가하기 위해서 사용된다.

Padding: 크기변화

특별한 사용용도는 없다. 단지 32bit 크기를 맞추기 위해서 사용되며, 0으로 세팅된다.


2.3절. 경로배정(routing)

IP 데이타 그램의 목적지까지의 경로 배정은 Destination Address 필드에 세팅되어 있는 IP 주소를 통하여서 이루어진다.
일단 데이타 그램이 보내질 목적지가 LAN 상에 존재하면, 데이타 그램은 곧바로 해당 목적지 호스트로 보내어진다. 그렇지 않을경우 데이타 그램은
설정되어 있는 default gateway(router) 로 보내어진다. 이것은 router
의 ip routing table 에 의해서 목적지까지 경우되어서 최종 호스트로 도착하게 된다. 여기에 대한 내용들은 이미 다른 기사에서 자세히
언급되어 있음으로 이정도에서 끝내도록 하겠다.


2.4절. 데이타 단편화 (fragmentation)

위에서 IP 헤더 필드를 설명하면서 “데이타 단편화” 에 대한 언급을 했었다. 이번장에서는 이러한 데이타 단편화가 일어나는 원인과 어떻게
단편화된 데이타를 재조합 할수 있는지에 대해서 알아보도록 하겠다.


2.4.1절. MTU(Maximum Transmission
Unit)

MTU 란 다음 호스트에 한번에 보낼수 있는 데이타 그램의 크기이다. 어쨋든 데이타를 한번에 몽땅 보낼수는 없으므로 호스트에서는 이것을
적당한 크기로 잘라내야 할것이다. 그런데 이 적당한 크기라는게 말그대로 적당한 크기로 망에 따라서 약간씩 그 크기가 다르며, 각 망에서
통신하기에 가장 최적화된 크기의 MTU를 가지고 있다. MTU 사이즈는 헤더를 제외한 data 만의 크기이다.

이러한 MTU 사이즈는 여러번의 테스트를 걸쳐서 각망에 최적화된다라고 생각되는 실험적인 크기로 정해진다. 우리가 보통 사용하는 이더넷 망의
경우 1500, ATM 망의 경우 9600 의 사이즈를 가지며, SLIP 의 경우 576 의 크기를 가진다. 또한 이 값은 망 상태에 따라서
네트웍 관리자에 의해서 임의로 조정될수 있다.

[root@localhost root]# ifconfig
eth0 Link encap:Ethernet HWaddr 00:50:BF:2C:7B:B2
inet addr:192.168.0.4 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:355481 errors:1 dropped:0 overruns:0 frame:0
TX packets:360573 errors:0 dropped:0 overruns:0 carrier:0
collisions:5023
RX bytes:369176288 (352.0 Mb) TX bytes:33374363 (31.8 Mb)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:68 errors:0 dropped:0 overruns:0 frame:0
TX packets:68 errors:0 dropped:0 overruns:0 carrier:0
collisions:0
RX bytes:3400 (3.3 Kb) TX bytes:3400 (3.3 Kb)

이러한 MTU 의 크기는 ifconfig 를 통해서 확인 가능하며, 변경도
가능하다. 위의 ifconfig 정보는 필자의 리눅스박스에서 측정한 크기이다. 필자의 리눅스 박스는 보통의 이더넷카드를 이용하므로 MTU
1500 으로 세팅되어 있다.


2.4.2절. 단편화및 재조립

인터넷은 다양한 환경을 가지는 망으로 서로 연결되어 있음으로, 데이타 그램이 목적지로 이동하는 동안 다양한 MTU 크기를 가지는 망을
통과하게 된다. 만약 1500 의 MTU 크기를 가지는 호스트에서 만들어진 데이타 그램이 576 MTU 크기를 가지는 SLIP 를 통과하게 되면
어떻게 될까 ? 1500 의 크기로는 576 크기를 통과할수 없음으로, 576 크기에 맞도록 데이타가 단편화 되게 된다.

   IPH : IP Header
+-----+------------------------+
| IPH | 1500 |
+-----+------------------------+

+-----+-----+ +-----+-----+ +-----+-----+
| IPH | 576 | | IPH | 576 | | IPH | 348 |
+-----+-----+ +-----+-----+ +-----+-----+

위의 그림처럼 1500 데이타는 2개의 576크기를 가지는 데이타 그램과 348
크기를 가지는 데이타 그램으로 단편화 되게 될것이다. 또한 이 데이타 그램은 단편화 된다고 하더라도, IP 데이타 그램의 특성을 가져야 함으로
각각 IP 헤더를 가지는 완전한 IP 데이타 그램의 형태가 될것이다.

이렇게 단편화 되어서 전송되는 데이타 그램의 경우 목적지에 서로 다른 순서로 도달할수가 있을것이다. 그러므로 단편화 작업을 수행할때,
각각의 단편화된 데이타 그램이 원래의 데이타그램의 어떤 위치에서 단편화 되었는지등의 정보를 넣어둠으로써 최종도착지점에서 단편화된 데이타를 다시
조립할수 있도록 만들어줘야 할것이다. 이러한 작업은 커널의 IP를 담당하는 모듈에서 자동적으로 수행하며, IP 테이블의 Flags 와
Fragment Offset 필드를 수정함으로써 단편화 정보를 유지하게 된다. 여기에는 현재의 데이타 그램의 단편화가 되어있는지 단편화가 되어
있다면, 어떤 데이타그램에서 단편화 된것인지, 몇번째 단편화 데이타 인지, 마지막 단편화 데이타 인지, 원래 데이타 그램에서 offset 은
어느정도가 되는지등의 정보가 들어가게 된다. 최종적으로 목적지에서는 데이타 그램의 Identification 과 Flag, Fragment
Offset 을 이용해서 단편화된 데이타를 재조립하게 될것이다.


2.5절. IP 헤더의 예

다음은 IP 헤더의 가장간단한 예로 단편화가 일어나지 않은 데이타 그램의 IP 헤더의 형태이다.

    0                   1                   2                   3  
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver= 4 |IHL= 5 |Type of Service| Total Length = 168 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification = 111 |Flg=0| Fragment Offset = 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time = 123 | Protocol = 1 | header checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| source address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| destination address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+

데이타 그램의 총 크기는 168bit 이고, 이중 헤더의 크기가 160bit
데이타의 크기가 8bit 임을 알수 있다. IPv4 버전이며, 단편화가 일어나지 않았(Flg=0)음을 알수 있다.

이번에는 좀더 복잡한 예로, 단편화가 일어난 데이타 그램의 경우이다. MTU 사이즈는 2048 이며, 보내고자 하는데이타의 크기는 2500
이라고 가정하겠다.

이것은 첫번째 데이타 그램이다.

    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver= 4 |IHL= 5 |Type of Service| Total Length = 2208 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification = 112 |Flg=1| Fragment Offset = 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time = 119 | Protocol = 6 | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| source address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| destination address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |


| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

데이타 그램의 총크기는 2048 + (32*5) = 2208 이 될것이다. 데이타
그램의 단편화가 이루어졌음으로 Flg = 1 이 세팅된다. 그리고 단편화된 데이타 중 첫번째 데이타 그램이므로 Fragment Offset 는
0이 될것이다.

다음은 두번째 데이타 그램이다.

    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver= 4 |IHL= 5 |Type of Service| Total Length = 612 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification = 112 |Flg=0| Fragment Offset = 2048 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time = 119 | Protocol = 6 | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| source address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| destination address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |


| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Identification 이 112 임을 주목하라. 마지막 단편화 데이타 이므로
(더이상 단편화된 데이타가 없음) Flg 가 0으로 세팅되어있다. 이 데이타 그램의 Total Length 는 (32 * 5) + (2500 –
2048) = 612 가 될것이다. 그리고 이 단편화된 데이타 그램이 원래 데이타 그램에서 단편화된 위치는 2048 이 될것임으로
Fragment Offset 는 2048 이 될것이다.


3절. 결론

이상 IP 프로토콜에 대한 좀더 자세한 내용들을 알아보았습니다. 이러한 내용들에 대한 좀더 자세한 내용을 원한다면 RFC791 와 W. Richard Stevens 의 TCP/IP Illustrated Volume
1 을 참고하기 바랍니다.

TCP/IP 란

TCP/IP 가 나타난 이유는 컴퓨터간 “통신”을 위해서 이다.
통신을 얘기할때 빠지지 않는것이
통신의 역사인데 – 언어, 북, 연기, 전화 … – 여기에서는 그러한 “통신”을 위한 도구의 변천사는 생략하겠다.
결론적으로 말해서
TCP/IP 는 가장최근에 나타난 컴퓨터와 컴퓨터를 통한 지역네트웍(LAN) 혹은 광역네트웍(WAN)간의 원할한 통신을 가능하도록 하기 위한
“통신규약(Protocol)” 이라고 생각하면 될것이다.

최초 미국방성에서 구축한 ARANET 라는 프로토콜에서 시작되었으며, 후에
미국방위통신청(DAC-Defense Communication Agency)에서 컴퓨터간 통신을 위해서 TCP/IP를 사용하도록 한것이 그 시초가
되었다.

TCP/IP가 인기를 구가하게 된건 인터넷의 등장이 그 결정적인 역활을 했으며, 가장 인기있는 인터넷 서비스인 “WWW”,
“EMAIL”, “TELNET”, “FTP” 등 대부분이 TCP/IP 기반에서 만들어져있다.
인터넷으로 연결된 수많은 컴퓨터와 통신을
위해서 TCP/IP를 선택한 이유는 그 개방성에 있는데, 즉 하드웨어, 운영체제, 접속매체에 관계없이 동작할수 있다는점때문에, 인터넷 통신을
위한 핵심으로 선택되었다. 현재는 수천만대의 컴퓨터가 인터넷을 통하여 거미줄처럼 연결되어 있다.

TCP/IP 란 이름에서 알수
있듯이, TCP/IP 는 TCP + IP 의 2개의 프로토콜로 이루어져 있는데, 통상 IP 프로토콜 위에 TCP 프로토콜이 놓이게 되므로
TCP/IP 라고 부르게 되었다.

  • IP – node(단말기)와 node 간의 데이타 패킷을 전송하기 위해서는 각 node 에 주소를 필요로 하는데(우편번호 같은) IP는
    4바이트로 이루어진 주소번호를 사용하여서 각각의 node 를 구분하고, 목적지를 찾아가게 된다. 우리는 이를 IP 넘버라고 하며,
    “192.168.100.100” 의 형식으로 사용하게 된다. IP 는 Internet Protocol 의 줄임말이다.
    숫자로된
    인터넷주소를 위어서 원하는 컴퓨터를 식별하는건, 그리 쉽지 않기 때문에, IP주소를 인간이 식별하기 쉬운 Domain 네임으로 변환시켜주는
    Name 서비스가 존재한다. 아무래도 www.yahoo.co.kr 이 211.234,109.2 이런것 보다는 외기가 수월할것이다.
  • TCP – 서버와 클라이언트간에 데이타를 신뢰성있게 전달하기 위해 만들어진 프로토콜이다. 데이타는 네트웍선로를 통해 전달되는 과정에서
    손실되거나 순서가 뒤바뀌어서 전달될수 있는데, TCP는 손실을 검색해내서, 이를 교정하고 순서를 재조합할수 있도록 해준다.
    Transmission Control Protocol 의 줄임말이다. 데이타를 전송하기 전에 데이타전송을 위한 연결을 만듦으로 연결지향 프로토콜
    이라고 한다.

LAN 과 WAN 그리고 TCP/IP

흔히 LAN 은 Local Area Network 의 줄임말로 우리나라 말로
풀어쓰자면 “지역내트웍(근거리 통신망)” 이며 WAN 은 Wide Area Network 의 줄임말로 “광역네트웍(원거리 통신망)” 으로
해석할수 있을것이다.
즉 LAN 은 지역적으로 가까운 컴퓨터가 서로 연결(Network)된 상태를 말하며 WAN은 지역적으로 멀리떨어진
컴퓨터가 서로 연결 된 상태를 말한다.

다음의 그림은 이러한 LAN과 WAN의 구성을 보여주는 가장 단적인 그림이다.

 +-------+  +-------+  +-------+      +-------+  +-------+  +-------+
| HOST1 | | HOST2 | | HOST3 | | HOST1 | | HOST2 | | HOST3 |
+-------+ +-------+ +-------+ +-------+ +-------+ +-------+
| | | | | |
| | | | | |
=============================== ===============================
LAN (Korea) | | LAN (Japan)
| |
+--------+ +--------+
| Router |---------| Router |
+--------+ +--------+

HOST 와 HOST 그리고 HOST 와 Router 는 다양한 종류와 다양한 품질을
가지는 네트웍연결 회선으로 연결될수 있다(광케이블, 구리선, 인공위성등…). 통화품질이 다르다는 것은 데이타를 보내는중 데이타 손상이
일어날수도 있으며, 데이타의 순서가 뒤바뀔수도 있다는걸 의미한다.
데이타의 순서가 뒤바뀔수 있는 이유는, 패킷이 전달되는데 하나의 고정된
전달 경로만을 이용하지 않고 임의의 경로를 사용하기 때문인데, 위에서 말했듯이 각경로를 구성하는 회선의 품질이 다르므로, 먼저 보내어진
패킷이라도 나중에 보내어진 패킷보다 더 느리게 도착할수 있기 때문이다.(구리선으로 전달되는 패킷은 인공위성이나 광케이블로 전달된 패킷보다
아무래도 느리게 움직일 것이다.) TCP/IP는 이러한 연결된 상태에서 서로 올바른 통신을 하도록 도와준다.
정확히 말하자면 TCP가
올바른 통신을 하도록 도와주는 기능을 가지고 있으며, IP는 이러한 기능없이 오로지 TCP 패킷을 전송하는 일만을 한다.
올바른 통신을
위해 TCP가 가지고 있는 기능은 “패킷이 빠졌을경우, 재전송을 요청하는 기능”, “패킷에 일련번호를 줌으로써, 패킷의 순서를 재조하하는 기능”
이다.

UDP와 TCP

위에서 데이타를 전송하기 위한 TCP 프로토콜에 대해서 설명했는데, TCP외에 UDP 라는 프로토콜
존재한다.
데이타를 전송한다는 점에서 TCP, UDP 모두 비슷하지만 특성에 있어서 약간의 차이가 있다. UDP 는 User
Datagram Protocol 의 줄임말이다.

  • TCP – 연결지향이며, 자체적으로 오류를 처리하며, 네트웍 전송중 순서가 뒤바뀐 메시지를 교정시켜주는 기능을 가지고 있다.
    연결지향이란말은 데이타를 전송하는 측과 데이타를 전송받는 측에서 전용의 데이타 전송 선로(Session)을 만든다는 의미이다. 데이타의 신뢰도가
    중요하다고 판단될때 주로 사용된다.
  • UDP – 비연결지향이며, 오류를 처리하거나 순서를 재조합시켜주는 기능을 가지고 있지않다. 단순히 데이타를 받거나, 던져주기만 하는
    프로토콜이다. UDP는 특히 실시간 멀티미디어 정보를 처리하기 위해서 주로 사용한다.
    TCP를 실시간 멀티미디어 정보를 처리하는데,
    사용할경우 TCP의 오류정정 특성상 메시지가 도착하지 않거나 할경우 다음 메시지를 받지 않고, 메시지 재전송을 요구하므로, 실시간으로
    전송하기에는 그리 적당하지 않기 때문이다.
    반면 UDP를 사용하면 중간에 패킷이 소실되더라도 개의치 않고 다음 패킷을 받아들이므로
    실시간으로 메시지 처리가 가능하다.
    물론 약간의 데이타 손실로 인한, 멀티미디어 데이타의 질이 떨어질수도 있으나, 화질이나 음질에 약간의
    손상이 있더라도 계속적으로 서비스가 되는게 훨씬더 유리할것이다.
    전화를 하는데, 약간 잡음이 섞인다고 해서, 잡은 정정하기 위해서 서로
    통화를 못하는 사태가 발생하면 안되는것과 같은 이치이다.

여기에서는 주로 TCP 에 대해서 다룰것이며, UDP는 필요할경우
약간식 부연설명하도록 하겠다.

어떻게 TCP/IP 를 이용해서 컴퓨터간 데이타 통신이 가능한가?

지금까지 TCP/IP 그리고 UDP에 대한 개괄적인
내용을 살펴봤는데, 해결되지 않은 문제가 있다. 그렇다면, 각 컴퓨터간을 연결해주는 이더넷 카드를 통해서 어떻게 TCP/IP 메시지가 전달되는
것일까 ?

이것을 이해하기 위해서는 “OSI 7 계층(Layer)”에 대한 이해가 필요하다.
OSI 는 각종 시스템간의
연결을 위하여 ISO 에서 제안한 모델로써, OSI(Open System Interconnection Reference Model)에서 유추할수 있듯이,
시스템에 상관없이 서로의 시스템이 연결될수 있도록 만들어주는 모델이다.
OSI 는 아래와 같이 7개의 계층으로 되어 있다.

+---------------------+
| Application Layer |
+---------------------+
| Presentation Layer |
+---------------------+
| Session Layer |
+---------------------+
| Transport Layer |
+---------------------+
| Network Layer |
+---------------------+
| Data Link Layer |
+---------------------+
| Physical Layer |
+---------------------+

컴퓨터와 컴퓨터사이의 데이타전송을 위해서는 위의 7개의 계층을 “직-간접적” 으로
거쳐서 전송이 되게 된다.
위와 같이 7개의 계층으로 나눈 이유는, 각 계층에 대한 캡술화와 은닉이 가능하기 때문이다. 캡슐화, 은닉에
대해서는 아마도 C++ 을 공부해 본적이 있다면 많이 들어본 개념일건데,
예를들어 서비스 개발자는 Application Layer 와
Prsentation Layer 만 신경쓰면 되며, 실지 어플리케이션 개발자는 Session Layer 와 Transport Layer 정도만
신경쓰면 될것이다. Network Layer 계층 아래로는 거의 신경쓸 필요가 없을것이다. 마찬가지로 하드웨어를 만드는 사람은 Physical
Layer 만 신경쓰면 되며, 그위의 계층에 대해서는 신경쓸필요가 없을것이다.(물론 개발자가 Application Layer 와
Presentation Layer 까지 몽땅 신경써서 개발하는 경우도 있지만 – 사실은 거의 대부분이겠지만)

OSI를 이렇듯
계층별로 나눔으로써, 각 계층에서 필요한 부분만을 개발자들이 신경쓰게 되고 통신서비스 개발시간을 줄일수 있도록 도와준다.

OSI 7 계층과 TCP/IP 4계층

TCP/IP 게층은 OSI 7계층을 더 단순화 시켜서 4개의 계층(Layer)로
만들어서 사용한다.

OSI 7 계층                   TCP/IP 4 계층
+---------------------+ +---------------------+
| Application Layer | | Application Layer |
+---------------------+ | |
| Presentation Layer | | |
+---------------------+ +---------------------+
| Session Layer | | Transport Layer |
+---------------------+ | |
| Transport Layer | | |
+---------------------+ +---------------------+
| Network Layer | | Internet Layer |
+---------------------+ | |
| Data Link Layer | | |
+---------------------+ +---------------------+
| Physical Layer | | Physical Layer |
+---------------------+ +---------------------+

1) Application Layer
이 계층은 네트웍을 사용하는
응용프로그램(FTP, Telnet, SMTP) 등으로 이루어지며, OSI 계층의 Aplication Layer 와 Presentation
Layer 를 모두 포함한다.

2) Transport Layer
계층의 이름에서 알수 있듯이, 도착을 원하는 시스템까지
데이타를 전송하기 위한 일을 하는 게층이다. OSI 모델의 Session Layer 과 Transport Layer 를 포함하고 있으며, 각각의
시스템을 연결하고, TCP 프로토콜을 이용하여 데이타를 전송한다.

3) Internet Layer
데이타를 정의하고 데이타의
경로를 배정하는일(라우팅)을 담당한다. 데이타를 정확히 라우팅 하기 위해서 IP프로토콜을 사용한다. OSI 의 Network Layer 과
Data Link Layer 를 포함한다.

4) Physical Layer
물리적 계층 즉 이더넷 카드와 같은 하드웨어를
말한다.

TCP/IP 4계층에 의한 데이타 전송

그럼 실제로 TCP/IP 4계층을 이용해서 어떻게 데이타가 전송되는지
알아보도록 하자. 아래는 이러한 계층 통신의 가장 단적인 모습을 보여주는 그림인데, 현재 가장 많이 사용하는 인터넷 서비스중 하나인 WWW 을
예를 들어 그림을 그려 보았다.

    +----------+        HTTP Protocol           +----------+
| Browser | <- - - - - - - - - - - - - -> | Server | Application Layer
+----------+ +----------+
↓↑ ↓↑
+----------+ TCP protocol +----------+
| TCP | <- - - - - - - - - - - - - -> | TCP | Transport Layer
+----------+ +----------+
↓↑ ↓↑
+----------+ IP protocol +----------+
| IP | <- - - - - - - - - - - - - -> | IP | Internet Layer
+----------+ +----------+
↓↑ ↓↑
+----------+ Ethernet Protocol +----------+
| Etnernet | <- - - - - - - - - - - - - -> | Etnernet | Physical Layer
+----------+ +----------+
↓↑ ↓↑
=========================================================
TCP/IP 패킷
INTERNET

WWW (World Wide Web)은 더이상 설멍이 필요없는 유명한 서비스로써,
HTTP (HyperText Transfor Protocol)이라는 프로토콜을 이용한다.
위의 그림을 설명해 보자면, 일단 사용자는
Mozilla 나 IE 같은 브라우저를 사용하여서 www.joinc.co.kr 같은 URL 입력을 통해서 웹페이지를 요청하게
될것이다.(www.joinc.co.kr 은 인간이 인식할수 있는 도메인명이고 Name 서비스를 이용하여 이것을 다시 IP 주소체계로 바꾸는
작업을 브라우저 내부적으로 하게 될것이다.)
그럼 사용자의 요청(문자 메시지가 될것이다)은 인터넷상에서 전달되기 용이한 패킷으로 만들기
위해서 TCP 패킷으로 만들어지게 될것이다.
이것은 다시 인터넷 상에서 원하는 주소로 이동할수 있도록 하기 위해서 IP 패킷으로 다시
만들어 지고(IP 패킷에는 자신의 주소와, 도착해야될 상대방의 주소정보가 들어있을것이다)
이것은 이더넷 카드로 보내어져서 Internet
으로 나가게 된다.
Internet 상에서는 원하는 주소로 TCP/IP 패킷을 보내기 위한 여러가지 장치들이 존재하는데(라우터, 토큰링
같은), 이들 장치를 통해서, www.joinc.co.kr 의 이더넷카드로 TCP/IP 패킷이 전달되게 된다.
그럼 이더넷 카드는
TCP/IP 패킷을 바로 윗 계층(Internet Layer)으로 보내는데, 여기에서는 IP 패킷을 분석해서, 이 패킷이 어디에서 왔으며, 그
도착지가 어디인지를 판단하게 된다.(물론 이는 IP주소 기반으로 판단한다)
그리하여 목적지가 자신이면 이것을 다시 Transport
Layer 로 보내고, TCP 프로토콜을 사용하여, 메시지가 누락된게 있으면 다시 요청하고, 순서를 재조합하는등 통신 메시지를 검사해서 이것을
다시 Application Layer 에게 보낸다
Application Layer 에서는 웹서버(IIS, Apache 같은)가
통신메시지를 HTTP 프로토콜에 준하여, 검사를 하여서 사용자가 요청한 웹페이지를 읽어들여서, Transport 계층으로 보내게 된다.

웹페이지를 브라우저까지 전송하는 과정은 위의 정반대의 과정을 순차적으로 거치게 된다.
최종적으로 웹브라우저는 웹페이지를
받아서(text) 역시 HTTP 프로토콜에 준하여, 렌더링 작업을 거친후 화면에 뿌려주게 된다.

위의 그림에서 보면 알겠지만
각각의 계층은 각각의 계층만을 상관하고 있음을 알수 있다. 즉 Application Layer 에 위치하는 브라우저와 webserver 는
HTTP 프로토콜에 의해서 자신의 계층끼리만 통신을 하고, Transport Layer 은 역시 TCP 프로토콜에 의해서 Transport
Layer 끼리 통시을 함을 알수 있을것이다.
말그대로 계층적 구조를 가지며, 각 계층은 대응되는 상대편의 계층에 대해서만 상관한다.

연결지향 이란 무엇인가?

TCP는 UDP와 달리 연결지향이라고 배웠었다. 그렇다면 연결지향이란 무엇을
의미하는것일까?
우리는 바로 위에서 TCP/IP 에 의해서 데이타가 어떻게 전송되어지는지를 알아봤는데, 데이타가 전송되기전에,
Browser 와 Server 간의 연결을 성립하는 과정이 데이타를 전송하는 과정전에 이루어지게 된다.
연결을 만드는 과정은 이를테면
우리가 전화할때 어떤내용을 말하기에 앞서서, “안녕하세요 ?” “누구누구씨 맞아요” “아내 저 누구누구 맞습니다”라고 상대편을 먼저 확인하는
과정과 동일한 과정이다.
즉 데이타가 전송되기 전에, 먼저 Browser 는 Server 에 “서버 잘있읍니까?” 라고 메시지를 보내고,
Server 는 다시 Browser 에게 “서버 준비되어 있으니, 데이타 보내시요” 라는 메시지를 보내고 Browser 는 다시 서버에게 “네,
그럼 지금부터 데이타를 보내겠습니다” 라고 서로 의 존재를 확인하는 절차를 수행한후, 정식 데이타를 교환하기 위한 통신선로를 개설하게 된다.
(통신선로를 하나 만들기 위해서는 3번의 데이타 전송이 일어나게 되므로, 이것을 세번악수 기법(Three handshake) 이라고 한다.
자세한 내용은 나중에..)
모든 정식데이타는 연결된 통신선로를 통해서 교환되게 되며, 이러한 이유로 TCP를 “연결 지향” 프로토콜이라고
부르는 것이다.

UDP 는 이러한 과정이 없이 단순히 데이타만을 전송함으로 “데이타 그램” 프로토콜이라고
부른다.

이상 TCP/IP 의 개념에 대해서 알아보았읍니다.
위의 내용은 제가 대학원에서 배우는 강의 내용을 공부도 할겸,
복습도 할겸 해서 만든 내용입니다. 그러므로 내용은 강의순서와 비슷하게 구성될겁니다.
다음 번엔 TCP/IP에 대한 좀더 자세한 내용에
대해서 알아보도록 하겠습니다.

출처 : Tong – 즐거운 하루가 되자님의 리눅스통

Leave a Reply

Your email address will not be published. Required fields are marked *