'Protocol'에 해당되는 글 4건

  1. 2010.03.22 ASN.1
  2. 2008.03.05 HTTP 트랜젝션의 구조
  3. 2007.05.14 connected UDP socket
  4. 2007.04.12 RTP(RealTime Transfer Protocol) (2)

ASN.1

진리는어디에 2010.03.22 21:18
ASN.1 이라는 것이 무엇인가?

.. 라고 묻는다면..구조화된 데이터(예를 들어 C++ 구조체 혹은 클래스 같은 것들.)에 대해서 기술하고, 인코딩하며, 그 데이터를 전송하고, 수신 하는 경우 디코딩 하는 방법들을 설명하는데 사용되는 일종의 표현법이다...라고 일단 설명 할 수 있겠다.

하지만 사실 이렇게 말하면 머리 속에 무슨 내용인지 쉽게 그림이 그려지지 않는다.(아..지금 이 글을 보는 그대는 그려지는가? 미안하다. 나는 그렇지 않다. 그래서 더 설명 해야겠다)

일단 ASN.1 이 기술한다는 구조화된 데이터,. 즉, 객체(object)라 하면 인/디코딩 하는데 있어 머신혹은 사용하는 언어 따라 천차만별의 방법을 가지는 경우가 종종 있다. ASN.1은 이런 방법에 대해서 어느정도 정규화된 규칙을 제
한다는 것이다.

하지만, 이것이 약간 역설적인 것이(아무도 그렇게 생각하지는 않지만 나는 그렇게 생각한다)..
ASN.1은 정보를 표현하는 추상적인 문법에 대해서는 정의를 하고 있지만 해당 정보가 인코딩 되는 방법에 대해서는 제약을 두고 있지 않다는 것이다. 따라서 여기저기서 다양한 ASN.1 인코딩 규칙들이 생겨날 수 있었고, 각 인코딩 규칙들은 데이터 값, 즉 정보들을 실질적으로 인코딩하여 바이너리 스트림으로 만들어 낼 수 있는 transfer syntax를 각 인코딩 버젼별로 생성해 낸다.

표준 ASN.1 인코딩 룰들로는 아래와 같은 것들이 있다 :

    - Basic Encoding Rules (BER)
    - Canonical Encoding Rules (CER)
    - Distinguished Encoding Rules (DER)
    - XML Encoding Rules (XER)
    - Packed Encoding Rules (PER)
    - Generic String Encoding Rules (GSER)

위의 각 ASN.1 인코딩 룰을 포함하여 ASN.1은 머신 아키텍쳐나 언어에 상관 없이 데이터 구조체를 기술함으로써 서로 다른 환경에 있는 두 어플리케이션간의 구조화된 데이터 전송을 가능하게 한다.

Example - ASN.1 표기법을 이용해 정의 된 FooProtocol 데이터 구조체 :

FooProtocol DEFINITIONS ::= BEGIN

    FooQuestion ::= SEQUENCE {
        trackingNumber INTEGER,
        question       IA5String
    }

    FooAnswer ::= SEQUENCE {
        questionNumber INTEGER,
        answer         BOOLEAN
    }

END

위의 코드에 잠깐 사족을 달자면, FooQuestion과 FooAnswer과 정의 되어 있지만, 사실 Answer가 먼저 보내지고, 그 응답으로 Question이 온다고 하더라도 ASN.1에서는 상관하지 않는다. ASN.1 이 정의하고 있는 것은  어디까지나 구조화된 데이터에 한정 될 뿐이고, 메시지의 전송 순서에 대해서는 관여하지 않는다.

다시 본론으로 돌아가서, 만일 FooProtocol을 따르는 메시지가 있다고 가정하자. 메시지는 아래와 같다  :

myQuestion FooQuestion ::= {
    trackingNumber     5,
    question           "Anybody there?"
}

이 메시지를 네트워크를 통해 수신측으로 전송하려면 위의 메시지를 바이너리 데이터 스트림으로 변환 해야 할 필요가 있다. 위에서도 계속 이야기 했지만 ASN.1은 이것을 위해 많은 방법을 정의하고 있고, 오늘 여기서는 그 방법 중 가장 간단한 방법인 Distinguished Encoding Rules (DER) 를 통해 데이터가 어떻게 인코딩 되는지 살펴 보도록 하겠다.

아래 예제는 위의 구조화된 데이터가 DER 포멧에 의해 인코딩 된 결과를 나타낸다 :

30 -- 'SEQUENCE' 임을 표시하는 태그
13 -- 전체 구조체의 길이를 16진수로 표시

02 -- 'INTEGER' 임을 표시하는 태그
01 -- 데이터의 길이를 16진수로 표시
05 -- 값

16 -- 'IA5String' 임을 표시하는 태그
0e -- 데이터의 길이를 16진수로 표시
41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f -- value ("Anybody there?" in ASCII)

참고로, DER에서 사용하고 있는 방식은  tag-length-value, 줄여서 TLV 라고 부르는 방식으로, 데이터 타입, 길이 값을 한 쌍으로 하여 묶어서 표시하는 방법이다.

암튼 위의 결과로 얻어지는 바이너리 스트림은 아래 처럼 된다. :

30 13 02 01 05 16 0e 41  6e 79 62 6f 64 79 20 74  68 65 72 65 3f

그렇다면 수신 측에서는 어떻게 해야 하는가? 수신측은 송신측과 같은 인코딩 룰을 사용해야 한다. 그리고 태그를 표시하기 위해 사용되는 바이트, 길이를 표시하기 위해 사용되는 바이트 등의 정보, 태그에 해당하는 데이터 구조체에 대한 정보는 미리 공유가 되어 있어야 한다. 간단하게 말하면 수신측, 송신측 동일한 DER 규칙과, 동일한 FooProtocol을 알고 있어야만 한다는 이야기다.

그 정보들을 기반으로 하여 수신측은 위의 바이트 스트림을 원래의 'myQuestion' 객체로 되 돌릴 수 있는 것이다(사실 myQuestion과 동일한 정보를 가지고 있는 객체를 하나 복사 할 수 있다는 것이 보다 더 정확한 표현일 듯 하다).

여기 까지 간단히 ASN.1에 대한 기본 개념과 기본 인코딩 룰에 대해서 알아 보았다.
이 문서로 궁금증을 모두 다 채우지 못한 분들은 아래의 링크들을 권한다 :
 * http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One : 위키피디아. ASN.1에 대한 설명
 * http://www.ncbi.nlm.nih.gov/Sitemap/Summary/asn1.html : ASN.1 요약
 * http://support.microsoft.com/kb/252648/ko : ASN.1과 BER에 대한 간단한 소개 - 한글
 * http://blog.naver.com/shieldguy?Redirect=Log&logNo=80023719812 - ASN.1에 대해서 기본 부터 자세히 적은 한글 사이트
Posted by kukuta

댓글을 달아 주세요

다른 여러 네트워크 프로토콜들과 마찬가지로 HTTP 역시 클라이언트-서버 모델을 가지고 있습니다. HTTP클라이언트는 서버로 향하는 컨넥션을 만들고 리퀘스트 메시지(request message)를 보냅니다. 응답을 마친 서버는 컨넥션을 닫아 버립니다. HTTP 컨넥션에 대한 지속적인 상태를 유지하지 않습니다. 이런 프로토콜 성향 때문에 HTTP를 비상태유지(stateless)프로토콜이라고 합니다.

요청 메시지와 응답 메시지의 포멧은 비슷합니다. 둘 다 텍스트 기반의 프로토콜이며 아래와 같은 메시지 구조를 갖습니다 :

  • 이니셜 라인(initial line)
    • 이니셜 리퀘스트 라인과 이니셜 리스폰스 라인, 두 가지로 구분 됩니다.
  • 헤더 라인
    • 헤더라인 자체가 없어도 되고 1개 이상의 헤더라인이 와도 상관은 없습니다.
    • header: value 형태로 구성 됩니다.
  • 공백라인
    • 헤더와 메시지 바디를 구분하는 아무 것도 없는 공백라인은 꼭 필요 합니다.
  • 메시지 바디(message body)
    • 메시지 바디는 필요에 따라서 사용해도 되고 사용하지 않아도 상관 없습니다.

보다 알아보기 쉽게 표현 하자면 아래와 같습니다 :

<initial line, request 와 response, 두 가지가 있습니다>
Header1: value1
Header2: value2
Header3: value3

<선택적으로 메시지 바디가 이곳에 오게 됩니다. 메시지 바디에는 데이터나 쿼리, $&*%!^$ 같은 바이너리 데이터 등이 올 수 있습니다>

이니셜 라인과 헤더는 반드시 CRLF로 끝을 맺어야 합니다. (보다 정확히 이야기 하자면 CR과 LF는 ASCII 코드의 13번과 10번 입니다)

Initial Request Line
리퀘스트를 위한 이니셜 라인과 리스폰스를 위한 이니셜 라인은 다릅니다. 이니셜 리퀘스트 라인은 스페이스 문자를 구분자로 하여 메소드 이름, 요청 되는 리소스의 로컬 패스, HTTP의 버젼 이렇게 세 부분으로 구성 되어 있습니다.

GET /path/to/file/index.html HTTP/1.0

Notes:

  • GET은 가장 일반적인 HTTP 메소드 입니다. 이 메소드는 "나에게 이 리소스를 주세요!" 라는 의미 입니다. 메소드의 이름은 항상 대문자로 쓰여야만 합니다. GET외에도 POST, HEAD 같은 메소드 들이 있습니다.
  • 패스는 호스트 이름 다음에 오는 URL의 나머지 부분입니다. 이것은 request URI 라고도 불립니다.
  • HTTP 버젼은 항상 "HTTP/x.x" 형태의 대문자여야 합니다The HEAD Method

HEAD 메소드
HEAD 메소드는 헤더에만 들어 있는 응답을 받는다는 것을 제외하면 GET 메소드와 비슷하다. 이 메소드는 요청하는 리소스의 정보를 체크하는데 유용하게 사용됩니다 :

  • HEAD 리퀘스의 응답은 절대 메시지 바디를 가지지 않습니다. 다만 스테이터스 라인과 헤더 라인만을 가집니다.

POST 메소드
POST 메소드는 클라이언트에서 서버측으로 보내는 메시지가 서버측의 프로그램에 의해 어떤 처리가 되어져야 할 때 사용됩니다. 예를 들어 CGI 같은 것들이 있습니다. POST 메소드는 GET 메소드와는 아래와 같은 것들이 차이를 보이고 있습니다 :

  • 리퀘스트와 함께 메시지 바디 안에 데이터 블록이 전송 됩니다. 메시지 바디를 전송하기 위해서 Content-Type: 와 Content-Length: 같은 헤더 라인이 추가 됩니다.
  • 리퀘스트 URI는 요청하는 자원의 경로가 아니라  전송하는 데이터를 처리해 줄 프로그램의 경로를 가리킵니다.
  • HTTP 응답은 고정된 파일이 아니라, 프로그램의 결과물입니다.

POST 메소드의 가장 일반적인 사용은 HTML의 form에서 CGI 스크립트로 submit을 할 경우입니다. 이 경우 Content-Type: 헤더는 주로 application/x-www-form-urlencoded로 셋팅되며, Content-Length: 는 URL형태로 인코딩된 데이터의 길이를 나타냅니다(note on URL-encoding). 이렇게 메시지를 전송하면 CGI는 STDIN으로 이 메시지들을 읽어들이고 디코딩 합니다 :

POST /path/script.cgi HTTP/1.0
From: frog@jmarshall.com
User-Agent: HTTPTool/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 32

home=Cosby&favorite+flavor=flies

데이터가 무엇이건 간에 상관 없이, HTML의 submit form을 이용하는 것에 상관 없이, POST 메소드는 모든 데이터를 전송이 가능합니다. 단지 송신자와 수신자간의 미리 약속된 포멧만 지켜주면 됩니다. 그리고 GET메소드 역시 submit form을 이용해 전송하는 것이 가능합니다. 보다 자세한 사항은more details 를 보세요.

Initial Response Line (Status Line)
이니셜 리스폰스 라인은 스테이터스 라인(status line)이라고 도 불립니다. 그리고 이니셜 리스폰스 라인도 이니셜 리퀘스트 라인처럼 세 부분으로 나뉘어 있습니다만 내용은 다릅니다. 구성은 HTTP 버젼,  리퀘스트 결과에 대한 정보를 가리키는 리스폰스 스테이터스 코드(response status code), 그리고 리스폰스 스테이스터스 코드에 대한 영어로 된 설명(reason phrase) 입니다. 일반적으로 아래와 비슷한 형태 입니다 :

HTTP/1.0 200 OK

이거나

HTTP/1.0 404 Not Found

이지요.

Notes:

  • HTTP버젼은 이니셜 리퀘스트 라인과 동일한 포멧인 "HTTP/x.x" 형태 입니다
  • 스테이터스 코드는 컴퓨터가 읽는 코드 입니다. 사람이 읽기 편한 것은 그 뒤의 reason phrase 입니다.
  • 스테이터스 코드는 3자리의 숫자로 되어 있습니다. 그리고 첫 번째 숫자는 각 결과의 카테고리를 구분하는 역할을 합니다 :
    • 1xx 정보 메시지만 담고 있음을 의미합니다
    • 2xx 특정 종류의 성공을 의미합니다
    • 3xx redirects the client to another URL
    • 4xx 클라이언트측의 에러를 의미합니다
    • 5xx 서버측의 에러를 의미합니다.

일반적으로 가장 많이 사용되는 스테이터스 코드는 아래와 같습니다 :

  • 200 OK 
    • 리퀘스트가 성공하고 결과 리소스가 메시지 바디에 들어 있음을 가리킵니다
  • 404 Not Found
    • 요청된 리소스가 없습니다
  • 301 Moved Permanently
    302 Moved Temporarily
    303 See Other
    (HTTP 1.1 only)
    • 리소스가 다른 URL로 옮겨졌음을 의미 합니다.
  • 500 Server Error

스테이터스 코드에 관련된 내용은 the HTTP specification (section 9 for HTTP 1.0, and section 10 for HTTP 1.1)을 참고 하시면 됩니다.

Header Lines
헤더 라인은 요청/응답 혹은 메시지에 실려 보내진 객체에 관련한 정보를 제공합니다.
헤더 라인의 포멧은 "Header-Name: value" 형식으로 되어 있고 CRLF(복귀와 개행문자)로 끝을 맺습니다. 이것은 RFC 822의 section 3에 정의 되어 있습니다 :

  • 헤더라인은 복귀문자와 개행문자(CRLF, \r\n)로 끝나야만 합니다.
  • 헤더의 이름은 대소문자 구분을 합니다(값도 아마 구분을 할 것입니다). 
  • ":" 와 값 사이에는 스페이스 문자나 탭 문자가 들어가야 합니다.
  • 스페이스 문자나 탭 문자로 시작하는 헤더라인은 이전 헤드라인에 연속입니다. 가독성을 위해 이 방법을 이용해 긴 한 줄을 여러줄로 나눌 수 있습니다. 

따라서 아래의 두 헤더는 동일 합니다 :

HEADER1: some-long-value-1a, some-long-value-1b
HEADER1: some-long-value-1a,
                some-long-value-1b

HTTP 1.0은 16개의 해더를 정해 놓았습니다만, 반드시 사용해야 할 필요는 없습니다. HTTP 1.1은 46개의 헤더를 정했고 한가지(Host:)는 반드시 넣어 줘야만 합니다. 네티켓을 지킬줄 아는 당신이라면 이 헤더들을 추가 하는 것을 고려 해 보는 것도 좋습니다 :

  • From: 헤더는 리퀘스트를 만든 사람의 이메일 주소를 기록합니다. 이 헤더는 사용자의 프라이버시를 위해 사용자가 선택적으로 기록할 수 있도록 해야만 합니
  • User-Agent: 는 리퀘스트 메시지를 만든 프로그램을 구분하는 헤더입니다. "Program-name/x.xx"와 같은 형식이에서  x.xx라는 것은 대부분 버젼을 나타냅니다. 예를 들어서 Netscape 3.0 은 "User-agent: Mozilla/3.0Gold" 과 같은 헤더를 만들어 냅니다.

이와 같은 헤더들은 웹마스터들이 여러가지 문제를 해결하는데 도움을 주기도 하지만 사용자의 정보를 노출 하기도 합니다. 만일 메시지에 특정 헤더를 포함하기로 했다면 사용자의 프라이버시와 웹마스터의 로깅자료에 대해서 적절한 타협점을 찾아야 합니다.

만일 서버를 만든다면, 응답(responses)에 아래의 헤더를 포함 시키는 것을 고려 해 보심도 좋을 것 같습니다 :

  • Server: 헤더는 User-Agent: 헤더와 유사합니다. Server: 헤더는 "Program-name/x.xx"포멧으로 서버측 프로그램을 구분 해 주는 역할을 합니다. 예를 들어 아파치 베타 버젼이 서버측에서 응답을 주고 있다면 서버는 "Server: Apache/1.2b3-dev"를 돌려 줄 것입니다.
  • Last-Modified: 헤더는 리소스의 최종 업데이트 시간에 대한 정보를 가지고 있습니다. 이것을 이용해서 캐싱된 데이터를 업데이트 하는데 사용 될 수 있습니다. 시간은 아래와 같은 포멧으로 표시 될 수 있습니다 :
    Last-Modified: Fri, 31 Dec 1999 23:59:59 GMT

Message Body
HTTP 메시지는 데이터 몸체(body of data)를 가질 수 있습니다. 응답의 경우에는 클라이언트로의 요청에 따른 결과 데이터 일 수도 있고, 에러가 발생 했다면 단순 에러 메시지 일 수도 있습니다. 요청의 경우에는 사용자가 입력한 데이터 이건나, 업로드를 하기 위한 데이터등 클라이언트로 서버로 보내지는 데이터들이 되겠지요.

만일 HTTP메시지에 바디(body)가 추가 된다면, 헤더라인에는 바디에 대해서 설명하는 헤더들이 추가 됩니다. 특히 :

  • Content-Type: 헤더는 text/htmlimage/gif 같은 데이터의 MIME-type 나타냅니다
  • Content-Length: 바디의 길이가 몇 바이트인지 나타냅니다

Sample HTTP Exchange
간단한 예제를 살펴 봄으로써 지금까지 설명했던 내용들에 대해서 되짚어 보도록 하겠습니다. 서버와 클라이언트 간에 오가는 메시지들을 직접 보시고 싶으시다면 웹서버에 텔넷을 이용하여 접속한 후, 직접 아래의 내용을 실습해 보는 것도 좋은 방법입니다.

아래의 URL에 있는 자원에 대한 요청을 보내 보도록 하겠습니다 :

처음으로 할 일은 www.somehost.com 호스트에 80번 포트로 연결되는 소켓을 생성하는 것입니다(왜 80번 포트냐면, 아무런 표시도 되어 있지 않은 HTTP는 기본적으로 80번 포트를 사용하도록 되어 있습니다). 소켓이 연결이 성공 했다면 아래의 메시지를 보내도록 합니다 :

GET /path/file.html HTTP/1.0
From: someuser@jmarshall.com
User-Agent: HTTPTool/1.0
[blank line here]

서버는 동일한 소켓으로 아래와 같은 형식의 메시지를 보내 줄 것입니다 :

HTTP/1.0 200 OK
Date: Fri, 31 Dec 1999 23:59:59 GMT
Content-Type: text/html
Content-Length: 1354

<html>
<body>
<h1>Happy New Millennium!</h1>
(more file contents) . . .
</body>
</html>

응답을 보낸 후, 서버는 해당 소켓을 닫습니다. 다음 요청을 위해서는 새로운 컨넥션을 만들어야만 합니다.

이상으로 HTTP 트랜젝션에 대한 설명을 마쳤습니다. 간단하게 요약설명만하고 마무리하고자 했는데, 아직 제 실력이 부족한지라 짧은 글로는 명확한 전달을 하지 못 하는군요.

여기까지 읽어 주셔서 감사합니다.

Ref :
 HTTP Made Really Easy : http://www.jmarshall.com/easy/http/

'진리는어디에 > Web' 카테고리의 다른 글

CSS 로딩하는 세 가지 방법  (0) 2008.04.19
CSS Selectors  (0) 2008.04.18
XMLHttpRequest 의 속성과 메소드  (2) 2008.04.17
HTTP 트랜젝션의 구조  (0) 2008.03.05
Posted by kukuta
TAG http, Protocol, Web

댓글을 달아 주세요

 일반적으로 UDP는 비연결 지향형 프로토콜로 알려져 있다. 맞는 말이다. 하지만 디폴트 UDP에 connect라는 것을 첨가하여 보다 편리 하게 쓸 수 있는 것도 사실이다.

 UDP소켓에다 connect 함수를 사용 한다는 것은 TCP의 그것 처럼 동작한다는 뜻은 아니다(Three-way handshaing 이라던지 하는 과정 들이 없다). 다만 커널에다 소켓이 향하고 있는 주소를 박아 넣어 send 할 때 마다 주소를 넘겨 줘야 한다는 것 외의 모든 동작방법이나 기타등등은 다 똑같다.

 자꾸 말을 번복하는 것 같지만, 내부에서 돌아가는 것은 다 똑같으나 사용법에 있어서 connected UDP와 unconnected(default) UDP는 다소 다른 점이 있다.

 * 더 이상 목적지 주소와 포트를 지정 할 필요가 없다.
   일반적으로 sendto 대신에 write를 사용하고, 꼭 sendto를 사용하고 싶다면, 목적지 주소(다섯번째 파라메터)
  는 NULL을 지정해야 하며, 주소 구조체의 크기(여섯 번째 파라메터)는 0이 되어야만 한다.

 * 데이터그램을 받기 위해 recvfrom을 사용 할 필요가 없다.
   read, recv, recvmsg를 대신 사용하게 된다. connect로 목적지 주소를 지정한 소켓은 그 주소에서 온 데이터그
  램만을 받아 들이고 다른 주소지의 데이터그램들은 무시하게 되므로, 주소를 알아내야 할 필요가 없다.


 * Asyncronous Error가 프로세스에게 리턴된다.
   예를들어 상대에게 UDP메시지를 보냈지만 목적 호스트에 메시지를 수신하는 프로세스가 없다고 가정하자. 상
  대측의 UDP는 ICMP unreachable 메시지를 다시 이쪽으로 반환 하겠지만 커널은 어떤 소켓에 그 메시지를 되
  돌려 줘야 할지 모른다. ICMP메시지가 UDP의 헤더의 사본을 가지고는 있지만, 스택은 어떤 어플리케이션이 그
  데이터그램을 보냈는지에 대한 정보가 없다.  하지만 소켓을 상대측의 주소와 연결한다면 이 사실은 소켓과 관련
  된 PCB에 기록될 것이고, UDP헤더의 사본을 PCB에 매치시켜 어떤 소켓이 ICMP메시지를 전달하는지 알 수 있
  게 된다.

 * BSD의 경우에는 약 1/3 정도의 성능 향상을 기대 할 수 있다.
   BSD에서 sendto는 특수한 경우로, sendto를 이용해 데이터가 전송 될 때, 커널은 소켓을 임시로 연결하고, 데
  이터그램을 전송하고, 그 후 소켓에 대한 연결을 끊는다.
 
   아래는 unconnected(default) UDP의 sendto 과정을 나타낸다.

    1. Connect the socket
    2. Output the first datagram
    3. Unconnect the socket
    4. Connect the socket
    5. Output the second datagram
    6. Unconnect the socket

   목적지로 두개의 데이터그램을 날려 보냈고, 하나의 데이터그램을 날릴때 마다 connect/unconnect과정을 거
  치고 있다. 하지만 어플리케이션이 여러개의 데이터그램이 한 peer로만 전송된다고 가정하고 connected UDP
  를 사용하게 되면 아래와 같은 과정으로 줄어 든다.

    1. Connect the socket
    2. Output the first datagram
    3. Output the second datagram

   4.3BSD와 이와 유사한 SunOS 4.1.1에 대한 연구 결과 [Partridge and Pink 1993]에서는 이런 방법으로 연결을
  설정하고 종료하는 것이 UDP 데이터그램 전송에 걸리는 시간의 1/3을 차지 한다고 한다. 이러한 UDP 코드는
  4.4BSD와 그 다음 버젼인 FreeBSD 등에서도 사실상 변하지 않고 남아 있다. 특히 이 스택들은 여전히 임시 연
  결과 임시 종료를 구현하고 있다. 따라서 연속되는 UDP데이터그램을 같은 상대측에 보내려고 한다면 먼저
  connect를 사용해서 효육의 향상을 기대 할 수 있다.

참고 : UNIX Network Programming
         Effective TCP/IP
         http://coolengineer.com/214

'진리는어디에' 카테고리의 다른 글

정규 표현식(Regular Expressions)  (0) 2007.08.31
커널 오브젝트 - 핸들  (0) 2007.07.23
connected UDP socket  (0) 2007.05.14
C++ operator 사용하기  (3) 2007.04.22
Threads Scheduling  (1) 2007.04.19
RTP(RealTime Transfer Protocol)  (2) 2007.04.12
Posted by kukuta

댓글을 달아 주세요

 일반적으로 생각하기에 '실시간 전송 프로토콜'이라는 단어를 말하면 A라는 호스트에서 어떤 이벤트가 발생하면 그와 동시에 B라는 상대편에서도 그 이벤트에 대한 인식을 할 수있을 것을 생각하곤 한다. 하지만 네트워크 상에서의 물리적인 제약으로 그런 실시간은 불가능하다. 아주 좋게 가정해서 전파가 빛의 속도로 전송 된다고 가정하자. 빛은 1초에 지구를 7바퀴 반을 돈다고 한다. 계산을 편하게 하기 위해서 1초에 10바퀴를 돈다고 하자. 그럼 우리 나라에서 지구 반대 편에 있는 미국으로 데이터를 전송하기 위해서는 1/10의 초의 절반 1/20초가 걸린다. 이것는 우리 나라에서 미국으로 직선으로 아무런 방해도 받지 않고 날아가는 아주 나이스한 경우의 이야기고, 미국 까지 가는 도중에는 수많은(?) 라우터를 거쳐 가야 하고 그 과정에서 버퍼링이라던지 라우팅이라던지 기타등등의 시간을 잡아 먹는 일들이 우리를 기다리고 있다. 물리적인 한계로 우리가 일반적으로 생각하는 '실시간 전송'이라는 것은 불가능하다는 뜻이다. 이런 의미의 실시간 전송을 가능하게 하는 사람이라면(아직 이 세상에 빛 보다 빠른 것은 발견되지 않았으므로) 노벨상을 받을 것이다.
 
 그렇다면 '실시간 전송 프로토콜'이라는 것은 과연 무엇이란 말인가? 실시간 전송을 설명하기 쉽게하기 위해 실시간 전송이 아닌 것에 대한 예를 들어 보자. 대표적인 예로 FTP 같은 것이 있다. 100M가 짜리 압축된 파일을 하나 다운 받는데 이것은 시간이 얼마가 걸리든 상관 없다. 1분내로 다운 받을 수 있으면 좋고, 1시간이 걸리든, 10시간이 걸리든 언젠가 모든 데이터를 순서에 맞게, 누락 없이 다 다운로드 받기만 하면 되는 것이다. 시간에 관계 없다는 소리다. 하지만 1시간 짜리 실시간 동영상을 본다고 하자. 이것은 모두 다운로드 받고 영화를 감상하는 것이 아니라 다운로드를 받으면서 감상을 하는 것이기 때문에 영화가 끝나기 전에는 모든 데이터들이 다운로드 완료 되어 있어야만 한다. 만일 밴드폭이 작어서 전송이 원활하지 못 하다면 유효기간이 지난(이미 지나간 장면의) 데이터는 전송을 하지 않으므로써 보다 원활하게 서비스 할 수 있다(물론 영화는 끊기겠지만).

 위와 같은 실시간 전송을 위해 고안된 프로토콜이 RealTime Transfer Protocol(이하 RTP)다. 실시간 전송의 특징(일반적으로 패킷 손실에 덜 민감하고, 딜레이 발생을 최대한 방지해야 함)에 맞게끔 보다 빠른 전송을 위해 TCP 보다는 UDP기반으로 구현 되었으며 UDP의 특성 답게 데이터의 무결성을 보장 하지 않는다.

 특징은 Pay-load type(어떤 타입의 컨텐츠가 전송 되는지를 나타내는 플래그), Sequence number(각 데이터그램에 붙여져 re-ordering에 사용), Time stamp(컨텐츠가 전송되는 시간 기록), Delivery monitoring 네 가지다.

 RTP는 아무런 QoS를 보장하지 않으므로 이를 보완 할 수 있는 메커니즘이 필요한데 여기에 RTCP(RTP Control Porotocol)이 사용된다. 사실 RTCP는 자체는 QoS를 보장하는 것이 아니라, 보장에 필요한 데이터들을 제공 할 뿐이다. 보통 RTCP는 RTP포트의 다음 포트를 사용하며, 일정 시간마다 한번씩 세션 내의 클라이언트(participant 라고 원문에는 되어있다)들에게 RTCP메시지가 보내어 진다. 이 메시지를 받는 클라이언트들은 그에 대한 응답을 보내 주고 이 데이터가 RTP를 사용하는 사람에게 제공 된다. 이 데이터들을 이용해서 어떻게 QoS를 보장 할 것인가는 사용자의 몫으로 남겨진다.
 
 한 가지 시나리오를 가정해 보자면 서버측에서 send byte를 세션내의 클라이언트들에게 보내고 클라이언트들은 자신이 받은 receive byte를 서버로 응답한다. 서버측에서는 그 값을 판단하여 클라언트들이 자신이 보낸 것에 비해 적은 양을 받고 있으면 데이터들을 보다 띄엄띄엄 보내 클라이언트에게 가해지는 부담을 덜어 주는 형식으로 flow control을 할 수있다. 이 외에도 많은 QoS 보장 방법이 있지만 그것은 구현에 따라 달라지므로 더 이상 언급하지는 않겠다.
 
 이 외에도 실시간 전송을 위해 사용되는 프로토콜들이 많이 있지만 나의 귀차니즘으로 인하여 여기서 이번 포스팅은 완료 하겠다. 보다 자세한 사항은 아래의 문서들을 참고 하길 바란다(무책임~)

참고 : RTP - http://en.wikipedia.org/wiki/Real-time_Transport_Protocol
         RTPC - http://en.wikipedia.org/wiki/Real_time_control_protocol
         http://blog.naver.com/dldbrud84/120025248792
         http://blog.naver.com/jejezz/50016197113
Posted by kukuta
TAG Protocol

댓글을 달아 주세요

  1. Favicon of http://blog.ggamsso.wo.tc/ BlogIcon 깜쏘 2007.04.12 14:57  댓글주소  수정/삭제  댓글쓰기

    무엇보다 RTP가 신기한건 QoS가 안되는데, 어느샌가 파일은 모두 다운되어 플레이되고 있다는 점이죠.
    뭐, 내부는 어떻게 돌아가는지 모르겠지만, mutlicast를 이용해서 부족한 대역폭을 해결하는 방법은 전혀 아니겠죠?
    multicast를 사용하면 하나의 패킷이 나아가면서 분배가 되겠지만, 그 전에 그 패킷을 받아 보겠다고 가입이 된 상태야 가능하죠.
    즉 회의시스템 같은 것에선 가능하지만...
    youtube같은건 그런게 전혀 없죠.
    하지만 RTP가 되기 위해서는 대역폭을 맞추는 것 보단, 압축률 높은 코덱을 개발하는게 빠르지 않을까 하는 생각이 드네요.
    그렇게 해서 나온게 h.263이고 x.264죠...

    물론 위의 이야기는 전부 영상에 관련된 이야기^^;;

    • Favicon of https://kukuta.tistory.com BlogIcon kukuta 2007.04.12 15:46 신고  댓글주소  수정/삭제

      위에 내가 RTPC가 QoS를 위해 존재 한다고 적어 놓았잖아. 거기에서 나오는 값(시퀀스 넘버, 타임스탬프 등등)을 가지고 QoS를 보장하는 거지.

      전송 할 때도 그냥 전송하는 것이 아니라 당연히 압축을 해서 전송하는 것이고 전송이 원활하게 이루어 진다면 그냥 압축률을 낮게 해서 보내고, 전송이 원활하지 못하다면 보다 압축률이 좋은 것으로 압축 알고리즘을 변경한다고 하더라.