1.UDP 프로토콜개요

TCP와 UDP의 공통점: 전송 계층 프로토콜이라는 점에서 다음과 같은 공통점이 있다.

- 포트번호를 이용해 주소를 지정한다.

- 데이터 오류를 체크한다. : TCP와 UDP는 IP의 패킷 전송 기능을 기반으로 동작한다. 전송 중 여러 원인으로 오류가 발생할 수 있는데, IP는 프로토콜 동작에 필수적인 IP 헤더에 대해서만 오류를 체크하고 데이터는 체크하지 않는다. 반면 TCP와 UDP는 헤더는 물론이고 데이터에 대한 오류도 체크한다.

TCP와 UDP의 차이점 

항목 

TCP 

UDP 

 1)

연결형(connection-oriented) 프로토콜

- 연결설정 후 통신 가능

비연결형(connectionless) 프로토콜

- 연결설정 없이 통신 가능 

 2)

신뢰성 있는 데이터 전송  신뢰성 없는 데이터 전송 
 3) 일대일 통신(unicast) 

일대일 통신(unicast), 일대다 통신(broadcast, multicast) 

 4)

데이터 경계 구분 안함

- 바이트 스트림(byte-stream) 서비스

데이터 경계 구분함

- 데이터그램(datagram) 서비스 

항목을 UDP 위주로 설명하면,

1) 연결 설정을 하지 않았으므로 connect() 함수를 사용하지 않는다. (몇가지 이유로 connect() 함수를 사용하는 경우가 있지만, UDP 프로토콜에는 연결 설정 개념이 없으므로 connect() 함수를 호출하더라도 특별한 패킷 교환이 일어나지 않는다.

2) 프로토콜 수준에서 신뢰성 있는 데이터 전송을 보장하지 않으므로, 필요하다면 응용 프로그램 수준에서 신뢰성 있는 데이터 전송 기능을 구현해야 한다.

3) 간단한 소켓 함수 호출 절차만 따르면 다자 간 통신을 쉽게 구현할 수 있다.

4) TCP와 달리 응용 프로그램이 데이터 경계 구분을 위한 작업을 별도로 할 필요가 없다.

 

※ UDP에 대한 오해

UDP는 신뢰성 없는 데이터 전송을 하므로 데이터 오류를 체크하지 않을 것이라고 생각하면 안된다. UDP는 TCP처럼 체크섬(checksum)을 이용해 데이터 오류를 체크한다. 그렇다면 TCP는 신뢰성 있는 데이터 전송을 하는데 왜 UDP는 그렇지 못 할까? 답은 UDP에서 데이터 재전송과 데이터 순서 유지 작업을 하지 않기 때문이다. UDP는 도착한 데이터에 오류가 있다고 판단하면 이 데이터를 응용 프로그램에 전달하지 않고 그대로 삭제해 버린다. 따라서 응용 프로그램은 데이터에 오류가 있어 버려졌다는 사실을 알지 못한다. 또한 TCP는 데이터 순서 유지를 위해 각 바이트마다 번호를 부여하지만 UDP는 비슷한 기능을 제공하지 않는다.

 

2. UDP 서버-클라이언트 동작 원리

UDP서버는 TCP 서버와 달리 멀티스레드 등의 프로그래밍 기법을 사용하지 않고도 한 소켓으로 여러 클라이언트를 처리할 수있다.

 (a) 서버는 소켓을 생성하고 클라이언트가 데이터를 보내기를 기다린다. 이 때 서버가 사용하는 소켓은 특정 포트 번호와 결합되어 이 포트번호로 도착한 데이터만 수신한다.

(b) 첫 번째 클라이언트는 연결 설정 없이 서버와 데이터를 바로 주고 받는다.

(c) 두 번째 클라이언트도 연결 설정 없이 서버와 데이터를 바로 주고 받는다. (TCP 서버와 달리 UDP서버는 소켓을 한개만 사용한다.)

(d) UDP 서버-클라이언트가 통신하는 일반적인 상황이다. 'UDP 클라이언트 #n' 처럼 한 클라이언트가 소켓을 두개이상 사용해 서버와 통신할 수 도 있다.

 

※ UDP서버-클라이언트모델(1)

 

주의 사항

- 블로킹 소켓을 사용할 경우, 송수신 함수의 호출 순서가 맞지 않으면 교착상태가 발생할 수 있다.

- 클라이언트는 데이터를 받은 후 송신자의 주소(IP주소,포트번호)를 확인해야 한다. recvfrom() 함수는 UDP 서버가 보낸 데이터는 물론, 전혀 다른 UDP 응용 프로그램이 보낸 데이터도 수신할 수 있기 때문이다.

 

※ UDP 서버-클라이언트모델(2)

=> UDP 클라이언트를 위와 같이 작성할 수도 있다. UDP 소켓에 대해 connect() 함수를 호출하면 통신할 상대의 주소 정보가 내부적으로 기억되므로 sendto()/recvfrom() 함수 대신 send()/recv() 함수를 사용해 특정 UDP 서버와 통신할 수있다.

장점

- sendto() 함수를 사용한 경우보다 효율적이다. connect() 함수로 서버주소를 한 번만 설정해 두면, send() 함수가 이 정보를 재사용하기 때문이다.

- 데이터를 받은 후 송신자의 주소(IP, 포트)를 확인하지 않아도 된다. recvfrom() 함수와 달리 recv() 함수는 connect() 함수로 설정한 대상을 제외한 다른 UDP 응용 프로그램이 보낸 데이터는 수신하지 않기 때문인다.

주의사항

- 블로킹 소켓을 사용할 경우, 송수신 함수의 호출 순서가 맞지 않으면 교착 상태가 발생할 수 있다.

 

※ UDP 데이터 전송 함수

1. sendto() 함수

1) 함수 원형

int sendto(

 SOCKET s, //통신에 사용할 소켓

 const char *buf, //보낼 데이터를 담고 있는 버퍼의 주소

 int len, // 보낼 데이터의 크기

 int flags, // sendto()함수의 옵션. 대부분 0을 사용. MSG_DONTROUTE(윈속에서는 사용하더라도 무시), MSG_OOB(UDP에서는 의미가 없음)가 있음

 const struct sockaddr *to, // 목적지 주소를 담고 있는 소켓 주소 구조체(UDP의 경우, 특정 호스트나 라우터 주소, 브로드캐스트나 멀티캐스트 주소를 사용할 수 있음)

 int tolen // 목적지 주소를 담고 있는 소켓 주소 구조체의 크기

);

2) sendto() 함수의 특징

sendto() 함수는 UDP 소켓은 물론, TCP 소켓에도 사용가능 하다. TCP 일때는 to와 tolen인자는 무시된다. 그리고 TCP 소켓에 사용할 때만, flags 인자에 MSG_OOB를 사용할 수 있다.

sendto() 함수로 보낸 데이터는 독립적인 UDP 데이터그램(패킷)으로 만들어져 전송되며, 수신측에서는 recvfrom() 함수 호출 한번으로 이 데이터를 읽을 수 있다. 따라서 UDP를 사용할 경우에는 TCP와 달리 응용 프로그램 수준에서 메시지 경계를 구분하는 작업을 할 필요가 없다.

UDP 소켓에 대해 sendto()함수를 호출할 경우, 한번에 보낼수 있는 데이터의 크기에 제한이 있다. 최소 0~최대 65507(65535-20(IP헤더크기)-8(UDP헤더크기)) 바이트이다. 실제로는 최대값보다 훨씬 작은 크기를 사용하는것이 바람직하다. 특히 UDP를 이용해 브로드캐스트 패킷을 보낼 경우, 512바이트보다 작은 크기를 사용할 것을 권고한다.(비주얼스트디오 설명서)

sendto()함수로 보낸 응용 프로그램 데이터는 커널(운영체제)영역에 복사되어 전송된 후 곧바로 버려진다. sendto() 함수가 리턴됐다고 실제 데이터 전송이 완료된 것은 아니며, 데이터 전송이 끝났어도 상대방이 받았는지 확인할 수 없다.

블로킹 소켓을 사용할 경우, 커널 영역에 데이터를 복사할 공간이 부족하면, sendto()함수는 호출 시 블록된다.

2. recvfrom() 함수

1) 함수 원형

int recvfrom(

 SOCKET s, // 통신에 사용할 소켓. sendto()함수에 사용하는 소켓과 달리, 이 소켓은 반드시 지역주소(IP, 포트)가 미리 결정되어 있어야 한다.

 char *buf, // 받은 데이터를 저장할 버퍼의 주소

 int len, // 버퍼의 크기. 도착한 UDP 패킷 데이터가 len보다 크면 len 만큼만 복사하고 나머지는 버린다. 이때 SOCKET_ERROR를 리턴한다.

 int flags, // 대부분 0을 사용. 사용가능한 값으로 MSG_PEEK, MSG_OOB(UDP에서는 의미가 없음)가 있다. recvfrom() 함수의 기본 동작은 수신버퍼의 데이터를 응용프로그램 버퍼에 복사한 후 해당 데이터를 수신버퍼에서 삭제하는 것인데, MSG_PEEK 옵션을 사용하면 수신 버퍼에 데이터가 계속 남는다.

 struct sockaddr *from, // 소켓 주소 구조체를 전달하면 송신자의 주소 정보로 채워진다.

 int *fromlen // 함수가 채워넣은 주소정보 구조체의 크기를 갖게된다.

);

2) recvfrom() 함수의 특징

recvfrom() 함수는 UDP 소켓은 물론이고, TCP 소켓에도 사용할 수 있으며, 이 경우, from과 fromlen 인자는 무시된다. TCP 소켓에 사용할 때만 flags 인자에 MSG_OOB를 사용할 수 있다.

sendto() 함수로 보낸 데이터는 독립적인 UDP 데이터그램(패킷)으로 만들어져 전송되며, 송신측에서는 recvfrom() 함수 호출 한번으로 이 데이터를 읽을 수 있다. 따라서 응용프로그램 수준에서 메시지 경계를 구분하지 않아도 된다.

UDP 소켓에 대해 recvfrom() 함수를 호출할 경우 리턴 값이 0이 될 수 있는데, 이는 상대방이 sendto() 함수 호출시 데이터 크기를 최소값 0으로 설정했다는 뜻이다. UDP 프로토콜에는 연결 설정과 종료 개념이 없으므로 recvfrom() 함수의 리턴 값이 0이라고 해서 특별한 의미가 있는 것은 아니다. 반면, TCP 소켓에서 recvfrom() 함수를 호출할 경우 리턴 값이 0이면, 정상종료를 의미한다.

블로킹 소켓을 사용할 경우, 소켓 수신 버퍼에 도착한 데이터가 없으면 recvfrom()함수는 호출 시 블록된다.

 

3. 브로드캐스팅

 

- 유니캐스팅(unicasting: one-to-one): 한 개체가 다른 한 개체에 데이터를 보내는 모델. IPv4, IPv6에서 지원

- 브로드캐스팅(broadcasting: one-to-many): 한 개체가 특정 네트워크(자신과 동일 네트워크도 가능)에 속한 모든 개체에 데이터를 보내는 모델. IPv4에서만 지원

- 멀티캐스팅(multicasting: ont-to-many): 동일 그룹에 가입한 모든 개체(물리적으로는 서로 다른 네트워크에 속할 수 있음)에 데이터를 보내는 모델. 개념적으로 브로드캐스팅은 멀티캐스팅의 특수한 경우로 볼수 있다. IPv4, IPv6에서 지원)

- 애니캐스팅(anycasting: one-to-one-of-many): 한 개체가 동일 그룹에 가입한 개체 중 가장 가까운 하나에만 데이터를 보내면, 데이터를 받은 개체가 그룹에 속한 나머지 개체에 데이터를 보내는 모델. IPv6에서만 지원)

 

※ 소켓응용 프로그램에서 브로드캐스트 데이터를 보내는 방법

① 브로드캐스팅을 활성화 한다.

BOOL bEnable = TRUE;

retval = setsocketopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&bEnable, sizeof(bEnable));

=> socket() 함수로 생성한 소켓은 기본적으로 유니캐스팅만 지원하지만, setsocketopt() 함수의 첫번째 인자로 해당 소켓, 두번째 SOL_SOCKET과 세번째 SO_BROADCAST 옵션, 네번째 TRUE 값을 사용하면 브로드캐스팅이 활성화된다.

② 브로드캐스트 주소를 목적지로 해서 데이터를 보낸다.

SOCKETADDR_IN remoteaddr;

ZeroMemory(&remoteaddr, sizeof(remoteaddr));

remoteaddr.sin_family = AF_INET;

remoteaddr.sin_addr.s_addr = inet_addr("255.255.255.255");

remoteaddr.sin_port = htons(9000);

char buf[BUFSIZE]; //송신용 버퍼를 선언하고 테이터를 넣는다.

...

retval = sendto(sock, buf, strlen(buf), 0, (SOCKET *) &remoteaddr, sizeof(remoteaddr));

if(retval == SOCKET_ERROR) 오류처리;

printf("%d바이트를 보냈습니다.\n", retval);

=>브로드캐스트 데이터를 보내는 코드는 IP 주소 부분을 제외하면 유니캐스트 데이터를 보내는것과 동일

 

※ 브로드캐스트 주소의 종류

IPv4 주소는 크게 네트워크 ID와 호스트 ID로 나눌수 있다. 서브넷을 사용하는 경우, 호스트 ID의 일부는 서브넷 ID로 사용된다. 브로드캐스트용으로 예약되어 있는 IPv4 주소는 아래와 같다. 

 

- 네트워크 브로드캐스트(net-directed broadcast)

호스트 ID 비트가 모두 1인 경우로 특정 네트워크에 대한 브로드캐스트를 의미한다. 브로드캐스트 데이터가 라우터를 거쳐야 하므로 라우터 설정에 따라 브로드캐스팅이 불가능할 수도 있다. 따라서 실용적으로 브로드캐스팅 주소로 사용하기는 어렵다.

 

- 서브넷 브로드캐스트(subnet-directed broadcast)

서브넷 ID를 제외한 호스트 ID비트가 모두 1인 경우로, 특정 서브넷에 대한 브로드캐스트를 의미한다. 서브넷 브로드캐스트도 라우터를 통과하지 못할 수 있으므로, 일반적으로 외부 서브넷에 대한 브로드캐스팅을 목적으로 사용하기는 어렵다. 하지만 송신자 자신이 속한 서브넷에 대한 브로드캐스팅은 항상 가능하다.

 

- 지역 브로드캐스트(local broadcast 또는 limited broadcast)

송신자 자신이 속한 네트워크에 대한 브로드캐스트를 의미한다. 항상 브로드캐스팅이 가능하며, 브로드캐스트 데이터가 라우터 경계를 넘어가지 않는다. 지역 브로드캐스트 주소는  ws2def.h파일에 INADDR_BROADCAST(0xffffffff; 255.255.255.255) 값으로 정의되어 있다.

 

"TCP/IP 윈도우 소켓 프로그래밍"책 에서 발췌

Posted by 초코송송이
l

Delphi String에 관하여..

 

Delphi 2007이하의 String Types 기준
 
3가지 타입이 있음.
  • Short strings.
  • Long strings.
  • Wide (Unicode) strings. 
 Type Maximum Length  Memory required  Used for 
 ShortString  255 characters  2 to 256 bytes  이전 버전과의 호환을 위해 존재함.
 AnsiString  ~ 2^31 characters   4 bytes to 2GB  8-bit (ANSI) characters, DBCS ANSI, MBCS ANSI, etc.
 WideString  ~ 2^30 characters  4 bytes to 2GB   유니코드. 다중사용자 서버나 다중언어 지원용 어플리케이션에서 사용.
(AnsiString: 때때로 long string 이라 불리며, 많은 목적으로 대부분 이걸 사용함.
WideString: .Net 플랫폼에서 주로 사용함.)  

Short String

델파이의 조상격인 Turbo-Pascal에서는 단지 한종류의 String 타입밖에 없었다. 바로 ShortString 타입이다. 터보파스칼 시절 ShortString은 디폴트 String 타입이었고, 우리가 단순하게 String으로 선언을 하면 기본적으로 ShortString이 선언이 되었다. ShortString은 기본적으로 힙에 생성이 되지 않고, 스택에 생성이 된다. 메모리 할당 관점에서 보면 ShortString은 다른 Integer, Boolean, Record, Enum타입등과 달리 정적할당 타입이다. 정적할당이다 보니 ShortString은 당연히 런타임시 사이즈가 변할수 없다. 그래서 ConCat(문자열 붙이는 함수), Insert(문자열에 추가하는 함수)등의 함수를 쓸 때 문제를 야기시켰다. 이 문제를 회피하기 위해, 터보파스칼(델파이)은 모든 String 인스턴스에 256바이트의 최대 사이즈를 미리 할당하였다. ShortString의 첫번째 요소는 String의 실제 길이를 나타내므로 ShortString은 최대 255 글자를 가질수 있다.

var S: ShortString;

 실제로 위와 같이 선언하면 스택에는 256 바이트가 사용된다. ShortString 변수가 지역변수이거나, 전역변수이거나 레코드나 클래스에 사용된다 해도 똑같이 256바이트가 사용된다. 

 ShortString의 메모리 구조는 아래와 같다. n은 문자가 문자열에 저장된 수이다.

 

원문: http://blog.naver.com/g2000240023?Redirect=Log&logNo=50021477287

http://www.codexterity.com/delphistrings.htm

 

Long Strings (AnsiString)

long string 이라고도 부르는 AnsiString은 동적으로 할당되는 문자열이다. 최대길이는 메모리가 허락하는 한도까지이다.
 
long string 변수는 4 바이트의 메모리 공간을 차지하는 포인터다.
문자열이 비어있을 때 (=길이가 0 일 때), 그 포인터는 nil 을 가리키며, 추가적으로 사용하는 공간은 없다. 문자열이 비어 있지 않을 때, 그 포인터는 문자열이 들어있는 동적할당된 메모리의 블럭을 가리킨다. 문자열 위치 이전의 8 바이트는 32-bit 길이의 지시자와 32-bit 길이의 레퍼런스 카운트로 이루어져 있다.
이 메모리는 힙 영역에 할당되지만, 이 메모리는 프로그래머가 관리하지 않고 전부 자동적으로 관리된다.
 
왜냐하면 long-string 변수들은 포인터이며, 둘 이상의 이 변수들은 추가적인 메모리의 소비없이 같은 값을 가리킬 수도 있기 때문이다.
컴파일러는 이 메모리를 이용해 자원을 절약하고, 실행속도를 향상시킨다.
long-string 변수가 해제되거나 생성될 때, 레퍼런스 카운트는 감소되거나 증가한다. string 을 가리키고 있던 레퍼런스 카운트가 0 이 되면 그 string 의 메모리는 해제된다.
이 프로세스를 레퍼런스 카운팅이라고 부른다.
인덱싱 과정에서 string 의 문자 하나를 바꿀 경우, 만약 그 레퍼런스 카운트가 1 보다 크다면 그 string 의 복사본이 생성된다.
이것을 가리켜 copy-on-write 라 한다.

원문: http://bloodguy.tistory.com/96 

아래는 델파당에서 검색한 내용을 옮겨보았습니다.

VCL의 String은 reference가 count됩니다. String은 변수는 그냥 포인터 4Byte입니다.
그런데 4Byte에 적힌 address위치에 가 보면 실제data가 있죠.

procedure TForm1.Button1Click(Sender: TObject);
var
    s: AnsiString;
begin

  s:='abcd';

  ShowMessage(IntToStr(sizeof(s)));      //'4'
  ShowMessage(IntToStr(sizeof(AnsiString))); //'4'
end;

위 코드에서 s의 size나  AnsiString의 크기는 4입니다.
즉 String변수는 포인터입니다.
실제 Data가 기록된 위치의 메모리 주소(Address)가 적힌 것입니다.

[AnsiStirng의 실제 기록 구조]

AllocSize =   ( StrRec+ 실제 Data ) 까지의 크기가 기록되어있습니다.
RefCount =  말그대로 reference-Count 로 AnsiString변수가 참조하고 있는 숫자입니다.
Length     =  실제Data의 길이입니다.

String의 길이를 구할때..
Delphi(VCL)의 AnsiString이   Lenth함수가  c에서 strlen보다 속도가 빠른데..
AnsiStirng의 Length를 구하면 위에 StrRec구조체에서  Length값을 그냥 return하지만
c에서 strlen은   $0 즉  NULL문자가 나타날때까지 처음부터 계속 search합니다.
그래서 AnsiString의 Length가 c의 strlen보다 속도를 비교할수 없을 정도로 빠르죠
참조  http://cafe.naver.com/bcbmaster/850

var
  s1,12: Stirng;
begin                                             // 1)

  s1:='abcd';                                  // 2)
  s2:=s1;                                       // 3)

  s2[1]='k';                                   // 4) 

end;                                             // 5)
  
위 소스에서 1) ~ 4) 과정을 설명해드리면...

1) AnsiString을 선언하면 스택에 4Byte 씩 2개 변수가 할당됩니다.
    문론 내용은 nil 아무것도 없습니다.

2) heap(힙)에   strrec(12Byte)포함하여 실제 data 4Byte까지 총 16Byte가 할당됩니다.

      AllocSize = 16
      RefCnt    =  1
      Length     = 4
      data = 'abcd'

      위와같이 메모리에 기록되고 stack에 s1위치에는 Data위치의 address가 기록됩니다. 

3)  s2:=s1 하면
      RefCnt = 2 로 바뀌고
      S2변수가 있는 stack위치에 Data가 s1과 똑같은 값 Data위치의 addr이 기록됩니다.

4)  s2의 값의 일부를 변경하면
       *  s1의 가리키던   StrRec의 RefCnt =1 로 바뀝니다.
       *  그리고 다시 또다른  힙에 14+8=22Byte의 메모리가 확보되고 다음과 같이 내용이 기록됩니다.
      AllocSize = 22
      RefCnt    =  1
      Length     = 4
      data = 'kbcd'            //실데이타  5Byte인데..  4의 배수로  할당되어서 8Byte가 할당됨
       * 그리고 s2의 stack위치값은  새로할당된 data의 힙address가 기록됩니다.

    음.. 그리고 AllocSize가 왜 12+data_length가 아니라 14+data_length인지는 저도 정확한 이유를 잘 모르겠네요
   
...
5) 함수를 빠져나가면 stack에   할당된 s1 , s2 가 삭제되겠죠

    string변수가 삭제 될때는 RefCnt가 하나씩 줄어듭니다.
    만약 RefCnt가 0이 될때면 메모리에 할당된 StrRec부터 Data까지 모두 free됩니다.


만약 전역변수에 문자열을 할당하면 전역변수의 내용을 바꾸지 않은한 RefCnt는 프로그램이 종료할때까지 항상  1보다 크겠죠

원문: http://www.delmadang.com/community/bbs_view.asp?bbsNo=17&bbsCat=41&indx=417354

 

WideString

WideString 타입은 동적으로 할당되는 16-bit 유니코드 문자로 이루어진 문자열을 의미하며, Win32 에서, WideString 은 COM BSTR 타입과 호환된다.
 Note: Win32 에서, WideString 은 레퍼런스 카운트를 이용하지 않는다.

 Win32 플랫폼은 싱글바이트, 멀티바이트뿐만 아니라 유니코드를 지원한다.

SBCS(single-byte character set) 에서 각 바이트는 문자열의 한 character이며,                     MBCS(multibyte character set)에서는 일부 character 는 1바이트 또는 그 이상의 바이트를 통해 표현된다.
MBCS에서 가장 첫번째 바이트는 lead byte 라고 불리며,
일반적으로, MBCS에서 하위 128 characters 들은 7-bit ASCII characters 이며, 127 이상의 character 를 결정하는 건 MBCS의 lead byte 이다.
null 값은(#0) 언제나 싱글바이트 문자이다.
 
유니코드 character set 에서 각 문자는 2바이트를 의미하며 유니코드 문자열은 1바이트의 나열이 아니라 2바이트의 나열이다.
Unicode characters 와 strings 는 또한 wide characters 와 wide character strings 로 불린다.
Unicode characters map 의 처음 245은 ANSI character set 이다.
윈도우즈 OS는 유니코드를 지원한다. (UCS-2) 
 
델파이는 Char, PChar, AnsiChar, PAnsiChar, AnsiString 타입을 통해 싱글바이트와 멀티바이트 문자(열)을 지원한다.
(멀티바이트 함수들은 보통 Ansi- 로 시작하는 이름을 가진다. 예를 들어, StrPos 의 멀티바이트 버전 함수는 AnsiStrPos 임)
멀티바이트 문자의 지원은 로케일 별 OS 에 의존적이며,  델파이는 WideChar, PWideChar, WideString 을 통해 유니코드를 지원한다.

원문: http://bloodguy.tistory.com/96 

 

Delphi 2009 이상

 상당히 오랫동안 Delphi에는 문자를 나타내기 위해 다음의 두 가지 개별적인 문자 타입들을 가지고 있었습니다.
AnsiChar: 8비트 표현을 사용 (256개의 기호들을 표시), 코드 페이지에 따라 다르게 해석됨
WideChar: 16비트 표현을 사용 (64K의 기호 표시)
 이 측면에서 Delphi 2009에 변화된 점은 없습니다. 달라진 점은, AnsiChar의 별칭이었던 Char 타입이 이제 WideChar의 별칭이 되었다는 것입니다. 컴파일러가 코드에서 Char를 발견할 때마다 WideChar로 해석합니다. 이런 새 컴파일러 디폴트를 변경할 수 있는 방법은 없습니다.이는 많은 소스 코드에 영향을 미치고 많은 결과를 양산하는 상당히 큰 변화입니다. 예를 들어 PChar 포인터는 이제 이전의 PAnsiChar가 아닌 PWideChar의 별칭입니다.

문자열과 UNICODESTRING

 Char 타입 정의에서의 변경 사항은 문자열 타입 정의에서의 변경 사항과 밀접한 관련이 있기 때문에 매우 중요합니다. 문자와는 다르게 문자열은 이전에는 없었던 새로운 데이터 타입(UnicodeString이라고 함)에 매핑됩니다. 내부 구조도 AnsiString 타입의 표현과는 상당히 다릅니다.
WideChar 타입에 기반한 문자열을 나타내는 WideString 타입이 언어에 이미 있는데, 왜 힘들게 새 데이터 타입을 정의해야 할까요? WideString은 참조가 카운트되지 않으며 성능과 유연성의 측면에서 매우 취약합니다. 예를 들어 WideString은 네이티브 FastMM4가 아닌 Windows 글로벌 메모리 할당자(allocator)를 사용합니다.
AnsiString과 마찬가지로 UnicodeString은 참조가 카운트되며 copy-on-write 의미를 사용하고 성능이 우수합니다. AnsiString과 달리 UnicodeString은 문자별로 2바이트를 사용하며 UTF-16을 기반으로 합니다. 사실상 UTF-16은 변수 길이 인코딩이며, 때때로 UnicodeString은 두 개의 WideChar 서로게이트 요소(즉, 4바이트)를 사용하여 단일 유니코드 코드 포인트를 나타냅니다.
문자열 타입은 이제 Char 타입에서와 마찬가지로 하드 코딩된 방식으로 UnicodeString에 매핑됩니다. 이를 변경할 수 있는 컴파일러 지시어나 다른 방법은 없습니다. 계속해서 AnsiString 문자열 타입을 사용해야 하는 코드가 있으면 해당 코드를 AnsiString 타입의 명확한 선언으로 교체해야 합니다.

문자열의 내부 구조

새 UnicodeString 타입과 관련된 주요 변경 사항 중 하나는 내부 구조입니다. 새로운 구조는 참조 카운트되는 문자열 타입 모두(UnicodeString 및 AnsiString)에 해당되며, 참조 카운트되지 않는 문자열 타입들(ShortString 및 WideString)에는 해당되지 않습니다.
기존의 AnsiString 타입의 구조는 다음과 같았습니다.

-8 -4  문자열 참조 주소 
 참조 카운트  길이 문자열의 첫 번째 문자 

첫 번째 요소(문자열 자체의 시작 부분부터 역으로 카운트)는 Pascal 문자열 길이이며 두 번째 요소는 참조 카운트입니다.

Delphi 2009에서는, 참조 카운트된 문자열의 구조는 다음과 같습니다.

-12

-10

 -8

-4

문자열 참조 주소

코드 페이지

요소 크기

참조 카운트

길이

문자열의 첫 번째 문자


길이와 참조 카운트 외에, 새로운 필드는 요소 크기와 코드 페이지를 나타냅니다. 요소 크기는 AnsiString과 UnicodeString 사이에 식별하는 데 사용되며, 코드 페이지의 경우는 UnicodeString 타입이 고정 코드 페이지 1200을 가지므로 AnsiString 타입에서만 의미를 갖습니다.

해당 지원 데이터 구조는 다음과 같은 System 유닛의 임플먼테이션 섹션에서 선언되어 있습니다.
type
    PStrRec = ^StrRec;
    StrRec = packed record
        codePage: Word;
        elemSize: Word;
        refCnt: Longint;
        length: Longint;
    end;
UnicodeString에 의해 리턴되는 코드 페이지는 1200이며, 이것은 글로벌 변수인 DefaultUnicodeCodePage에 저장되어 있는 숫자 값을 리턴한 것입니다. 위의 코드와 결과에서 Length는 문자 수를 리턴하므로 문자열 길이를 바이트 단위로 확인할 수 있는 직접적인 호출은 없습니다.
물론 다음 표현식을 사용하여, 길이 값에 각 문자의 바이트 크기를 곱하여 문자열 길이의 바이트 값을 알 수 있습니다.
Length(str1) * StringElementSize(str1)

(자세한 사항은 문서 참조)

참조문서: http://www.google.co.kr/url?sa=t&rct=j&q=delphi%20%EB%AC%B8%EC%9E%90%EC%97%B4%20%EA%B5%AC%EC%A1%B0&source=web&cd=1&ved=0CC8QFjAA&url=http%3A%2F%2Fwww.devgear.co.kr%2Fpdf%2Fmarco_cantu_delphi_and_unicode_kor.pdf&ei=Bc17T-6_I8ORiQfGnaCiCQ&usg=AFQjCNE0oq_js4cy2BaiEJ0aVFNAe4BUPg&cad=rjt 

 

Posted by 초코송송이
l
SIP(Session Initiation Protocol)

SIP(Session Initiation Protocol)는 텍스트 기반의 응용 프로그램 계층 신호 및 호출 제어 프로토콜로, HTTP(HyperText transfer Protocol)와 유사합니다. SIP는 SIP 세션을 작성, 수정, 종료하는 데 사용되며, 유니캐스트 및 멀티캐스트 통신을 모두 지원합니다. SIP는 텍스트 기반이기 때문에 구현, 개발 및 디버깅이 H.323보다 간단합니다.
(H.323은 멀티미디어 화상회의 데이터를 TCP/IP와 같은 패킷 교환 방식의 네트웍을 통해 전송하기 위한 ITU-T의 표준이다. 여기에는 고품질 비디오를 위한 LAN 표준, 그리고 28.8 Kbps 정도의 느린 회선을 통해 저주파수 대역의 비디오를 전송하기 위한 인터넷 표준 등이 포함되어 있다.)

SIP 구성요소

주요 SIP 환경 구성 요소는 두 가지 기본 범주인 SIP 서버와 SIP 사용자 에이전트로 구분됩니다.

SIP 서버

SIP 서버에는 프록시, 레지스터 및 리디렉션의 세 가지 유형이 있습니다. table 1에서와 같이 각 서버 유형은 다른 기능을 수행합니다. 서버가 수행하는 기능에 따라 처리되는 SIP 요청이 결정됩니다.

표 1   SIP 서버

SIP 서버 기능
프록시 서버 SIP 사용자 에이전트 클라이언트와 SIP 사용자 에이전트 서버 간의 중간 단계로 사용됩니다. 프록시 서버는 클라이언트와 서버 간의 통신 방향에 따라 SIP 사용자 에이전트 클라이언트나 SIP 사용자 에이전트 서버의 기능을 수행합니다. 프록시 서버는 SIP 요청을 전달하거나, SIP 요청을 전달하기 전에 수정할 수 있습니다.
레지스터 서버 사용자 에이전트의 IP 주소와 SIP 주소, 즉 URL(Uniform Resource Locator)을 포함하는 REGISTER 요청을 수신합니다. 이를 통해 레지스터 서버는 REGISTER 요청을 보낸 사용자 에이전트의 위치를 추적할 수 있습니다.
리디렉션 서버 호출 사용자 에이전트로부터 SIP 세션의 초기화를 SIP INVITE 요청의 형태로 수락하고, 호출된 사용자 에이전트의 올바른 SIP 주소를 검색하며, 해당 SIP 주소로 호출 사용자 에이전트에 응답합니다. 그런 다음 호출 사용자 에이전트는 해당 SIP 주소를 사용하여 호출된 사용자 에이전트와의 SIP 세션을 바로 시작합니다.

SIP 서버(프록시, 레지스터 및 리디렉션)는 별도의 응용 프로그램으로 개발되거나, 모든 서버 기능을 결합하는 단일 응용 프로그램으로 개발될 수 있습니다. 레지스터 및 프록시 서버가 결합된 것을 종종 랑데부 서버라 합니다.

SIP 사용자 에이전트

표 2 에는 두 가지 유형의 SIP 사용자 에이전트와 그 기능이 나열되어 있습니다.

표 2   SIP 사용자 에이전트

     SIP 사용자 에이전트      기능
사용자 에이전트 클라이언트   SIP 요청을 시작합니다.
사용자 에이전트 서버 SIP 요청을 수신합니다.

각 사용자 에이전트는 SIP 주소와 연관됩니다.

SIP 호출 흐름

SIP 세션의 호출 흐름은 SIP 세션이 SIP 사용자 에이전트 간에 직접 설정되었는지 아니면 SIP 서버(프록시, 레지스터 또는 리디렉션)가 SIP 사용자 에이전트 사이에 있는지 여부에 따라 달라집니다.

그림 2는 두 사용자 에이전트 간의 일반적인 호출 흐름을 보여 주며 각 단계는 괄호로 되어 있습니다. 우선 사용자 에이전트 A는 호출을 시작하기 위해 INVITE 요청을 보냅니다. 그러면 사용자 에이전트 B는 호출 요청이 처리 중임을 나타내는 시도 중 응답 코드(100)로 응답합니다. 사용자 에이전트 B가 호출을 수락했음을 나타내는 확인 응답 코드(200)로 응답하면 사용자 에이전트 A는 사용자 에이전트 B의 최종 응답 코드를 사용자 에이전트 A가 수신했음을 나타내는 승인(ACK) 요청으로 사용자 에이전트 B에 응답합니다. 문서 뒷부분에 나오는 'RTP 및 RTCP'에서 설명하는 바와 같이, 실시간 데이터가 RTP 패킷으로 캡슐화 되어 사용자 에이전트 A와 B 사이에 전송되고 나면, 사용자 에이전트 A 또는 B는 사용자 에이전트가 세션을 종료하고자 함을 나타내는 BYE 요청을 보낼 수 있습니다. 그러면 사용자 에이전트 B는 요청 성공을 나타내는 확인 응답 코드(200)를 사용자 에이전트 A에게 보냅니다.

rtcpro02

그림 2   사용자 에이전트 SIP 호출 흐름

그림 3은 두 사용자 에이전트 경로 사이에 프록시 서버가 있을 경우의 일반적인 호출 흐름을 보여 줍니다. 프록시 서버는 기본적으로 사용자 서버 및 사용자 에이전트의 기능을 모두 수행하는 통신 중간 지점으로 사용됩니다. 사용자 서버로 작동할 경우 프록시는 SIP 요청을 수신하여 대상 사용자 에이전트로 전달하고, 사용자 에이전트로 작동할 경우 SIP 응답을 수신하여 대상 사용자 에이전트로 전달합니다

그림 3   프록시 서버 SIP 호출 흐름

그림 4는 사용자 에이전트와 레지스터 서버 간의 일반적인 호출 흐름을 보여 줍니다. 레지스터 서버는 사용자 에이전트가 도달할 수 있는 주소를 나타내는 사용자 에이전트의 REGISTER 요청을 수락합니다. 레지스터 서버는 일반적으로 프록시 또는 리디렉션 서버와 함께 위치합니다.

rtcpro04

그림 4   관리자 서버 SIP 호출 흐름

그림 5는 리디렉션 서버가 두 사용자 에이전트 사이에 있을 경우의 일반적인 호출 흐름을 보여 줍니다. 사용자 에이전트 A가 호출을 시작하기 위해 INVITE 요청을 보내면, 리디렉션 서버는 사용자 에이전트 B가 일시적으로 이동했음을 나타내는 이동됨 응답 코드(302)로 응답합니다. 이어서 사용자 에이전트 A는 리디렉션 서버의 응답 코드를 사용자 에이전트 A가 수신했음을 나타내는 ACK 요청으로 응답합니다. 그러면 사용자 에이전트 A는 사용자 에이전트 B의 새로 얻은 주소로 또 다른 INVITE 요청을 바로 보냅니다.

rtcpro05

그림 5   리디렉션 서버 SIP 호출 흐름

샘플 SIP 아키텍처

그림  6은 샘플 SIP 아키텍처를 사용하여, SIP 구성 요소 간 통신이 처리되는 방법 및 SIP 구성 요소를 네트워크 환경에 맞추는 방법을 설명합니다.

그림 6   샘플 SIP 아키텍처

A. Datum Corporation은 회사 내 도메인 간에 SIP 요청을 전달하는 두 개의 SIP 프록시 서버를 가지고 있습니다. 방화벽에 연결된 SIP 프록시 서버는 회사 외부의 수신자에게 보내지는 모든 SIP 메시지와 회사 외부에서 내부의 수신자에게 보내지는 모든 메시지를 처리합니다. 예를 들어, A. Datum Corporation의 SIP 클라이언트에서 Fabrikam, Inc.의 SIP 클라이언트에게 전송되는 SIP INVITE 메시지는 Fabrikam, Inc.의 SIP 프록시 서버로 보내집니다.

그런 다음 SIP 프록시 서버는 SIP INVITE 요청을 Fabrikam, Inc.의 SIP 프록시 서버 도메인에 있는 대상 SIP 클라이언트 컴퓨터나 SIP IP 전화로 전달합니다. 예를 들어, Fabrikam, Inc.의 SIP 서버는 국제 전화 번호 형식으로 SIP URL과 함께 보내진 SIP INVITE 요청을 수신할 수 있습니다. 국제 전화 번호에 Fabrikam, Inc.의 SIP IP 전화 대상이 있을 경우 SIP INVITE 요청은 SIP IP 전화로 바로 전달됩니다. 반면, 국제 전화 번호에 아날로그 전화와 같은 SIP IP 전화 외의 대상이 있을 경우 SIP INVITE 요청은 PSTN에 맞게 SIP INVITE 요청의 서식을 지정하는 SIP/PSTN 게이트웨이로 전달됩니다. 회사의 PBX(Private Branch Exchange)는 국제 전화 번호를 사용하여 호출을 회사 내의 아날로그 전화로 라우팅할 것인지 아니면 회사 외부의 아날로그 전화용 PSTN으로 라우팅할 것인지를 결정합니다.

SIP 프로토콜

SIP 메시지는 RFC 822, 'Standard for the Format of ARPA Internet Text Messages'에 설명되어 있는 바와 같이 table준 인터넷 메시지 형식에 기초합니다. (http://www.microsoft.com/windows/reskits/webresources/ 의 웹 리소스 페이지  참조) SIP 메시지는 클라이언트에서 서버로 보내지는 요청이나 서버에서 클라이언트로 보내지는 응답입니다.

각 SIP 메시지는 표 3에서 보는 바와 같이 세 부분으로 구성됩니다.

표 3   SIP 메시지 부분

SIP 메시지 부분 정의
시작 줄 메시지가 요청인지 아니면 응답인지에 따라 콘텐트가 달라집니다. 요청 및 응답 시작 줄은 모두 SIP 버전을 포함합니다. 또한 요청 시작 줄은 메서드 유형과 요청을 수신하는 대상의 일반 URL 또는 SIP 주소를 포함하며 응답 시작 줄은 요청에 대한 응답을 정의하는 숫자 상태 코드와 응답구를 포함합니다.
헤더 헤더 유형과 관련 변수를 포함합니다.
메시지 본문 SDP(Session Description Protocol)에서 제공한 정보(예: SIP 세션의 미디어 기능에 대한 설명)를 포함합니다.

SIP는 시작 줄과 헤더의 값을 정의하며 SDP(Session Description Protocol)는 메시지 본문 값을 정의합니다.

SIP 메시지 시작 줄

표 4에 설명되어 있는 바와 같이 시작 줄 구문은 메시지가 요청인지 응답인지에 따라 달라집니다.

표 4   시작 줄 구문

시작 줄 구문
요청 메서드, 요청 URI, SIP 버전
응답 SIP 버전, 상태 코드, 응답구

요청 메서드

요청 시작 줄의 첫 번째 항목은 신호 명령인 SIP 메서드입니다. table 5에 나열된 SIP 메서드는 RFC 3261, 인터넷 초안 'SIP Extensions for Presence' 및 'SIP Extensions for Instant Messaging'에 정의되어 있습니다.

표 5   SIP 메서드 및 그 기능

SIP 메서드 기능
INVITE SIP 세션을 시작하기 위한 요청입니다. INVITE는 발신자로부터 수신자에게 보냅니다.
ACK 수신자가 호출을 수락했습니다. ACK는 발신자로부터 수신자에게 보내집니다.
OPTIONS 발신자가 수신자에게 자체 기능으로 응답할 것을 요청하고 있습니다.
BYE 세션을 종료하기 위한 요청입니다. BYE는 발신자나 수신자가 보낼 수 있습니다. BYE를 수신하는 당사자가 BYE로 응답할 필요는 없습니다.
CANCEL 일시 중지된 요청을 취소합니다.
REGISTER 발신자가 현재 위치를 관리자 서버에 등록하기를 원합니다.
SUBSCRIBE 발신자가 수신자의 상태 정보에 대한 업데이트를 요청합니다.
NOTIFY 자신의 업데이트된 상태를 가입한 당사자 자체에 전달합니다.
MESSAGE 인스턴트 메시지를 보내는 데 사용됩니다.

요청 URI

요청 시작 줄의 두 번째 항목은 수신자 URL을 포함하는 요청 URI(Uniform Resource Identifier)입니다. 일반적으로 이 URI는 여러 형식 중 하나를 가질 수 있는 SIP URL입니다. table 6에는 지원되는 형식 중 일부가 나열되어 있습니다.

표 6   SIP 요청 URL 형식의 일부 목록

SIP URL 형식 설명
sip:user@reskit.com 기본 SIP URL입니다.
sip:user@reskit.com;transport=TCP TCP의 전송 프로토콜 대상을 포함하는 기본 SIP URL입니다. 전송 프로토콜이 지정되지 않은 경우 기본값은 UDP입니다.
sip:user@172.16.20.54 IP 주소를 포함하는 SIP URL입니다.
sip:+1-425-707-9796@reskit.com;user=phone 국제 전화 번호를 포함하는 SIP URL입니다.
sip:marketing@reskit.com;maddr=225.0.2.1;ttl=64 이전에 지정된 호스트 이름을 무시하는 멀티캐스트 주소를 포함하는 SIP URL입니다. TTL(Time-To-Live) 값은 64(0-255)로 설정됩니다. 멀티캐스트 주소와 UDP를 전송 프로토콜로 사용할 경우 TTL을 설정해야 합니다.

요청 또는 응답 버전

요청 시작 줄의 마지막 항목이자 응답 시작 줄의 첫 번째 항목은 SIP 버전(현재 2.0)입니다.

Windows Messenger 세션에서 가져온 다음 샘플 SIP 요청 메시지는 일반적인 SIP 요청 줄을 보여 줍니다.

응답 상태 코드

상태 코드에는 정보, 성공, 리디렉션, 클라이언트 오류, 서버 오류 및 전역 실패의 6개 범주가 있습니다. table 7에 나온 것처럼 상태 코드의 맨 왼쪽 숫자는 코드의 범주를 나타냅니다.

표 7   SIP 응답 상태 코드

상태 코드 응답 범주 설명
1xx 정보 요청이 수신되었으며 처리 중입니다.
2xx 성공 요청된 작업을 성공적으로 이해 및 수락했습니다.
3xx 리디렉션 요청을 완료하기 위해 추가 작업이 필요합니다.
4xx 클라이언트 오류 요청에 잘못된 구문이 포함되어 있거나 서버에서 요청을 이행할 수 없습니다.
5xx 서버 오류 서버가 요청을 수신했지만 이를 처리할 수 없으며 다른 서버의 경우에는 요청을 처리할 수도 있습니다.
6xx 전역 실패 요청을 수신하는 서버에서 이를 처리할 수 없으며 다른 서버에서도 요청이 실패할 것입니다. 따라서 요청을 전달해서는 안 됩니다.

응답구

표 8에는 SIP 버전 2.0에 정의된 모든 SIP 응답 코드와 해당 범주 및 응답구가 나열되어 있습니다.

표 8   SIP 응답 상태 코드 및 응답구

상태 코드 응답 범주 응답구
100 정보 시도 중
180 정보 신호가 울림
181 정보 호출 전달 중
182 정보 대기
200 성공 확인
300 리디렉션 다중 선택
301 리디렉션 영구적으로 이동됨
302 리디렉션 임시로 이동됨
303 리디렉션 기타 참조
305 리디렉션 프록시 사용
380 리디렉션 대체 서비스
400 클라이언트 오류 잘못된 요청
401 클라이언트 오류 권한이 없음
402 클라이언트 오류 지불 필요
403 클라이언트 오류 사용할 수 없음
404 클라이언트 오류 없음
405 클라이언트 오류 메서드 허용 안 함
406 클라이언트 오류 받아들일 수 없음
407 클라이언트 오류 프록시 인증 필요
408 클라이언트 오류 요청 시간 초과
409 클라이언트 오류 충돌
410 클라이언트 오류 없음
411 클라이언트 오류 길이 필요
413 클라이언트 오류 요청 엔터티가 너무 큼
414 클라이언트 오류 요청 URI가 너무 김
415 클라이언트 오류 지원되지 않는 미디어 유형
420 클라이언트 오류 잘못된 확장
480 클라이언트 오류 일시적으로 사용할 수 없음
481 클라이언트 오류 호출 레그/트랜잭션 없음
482 클라이언트 오류 검색된 루프
483 클라이언트 오류 홉이 너무 많음
484 클라이언트 오류 주소가 완전하지 않음
485 클라이언트 오류 모호함
486 클라이언트 오류 여기에서 사용 중
500 서버 오류 서버 내부 오류
501 서버 오류 구현되지 않음
502 서버 오류 잘못된 게이트웨이
503 서버 오류 서비스 사용할 수 없음
504 서버 오류 게이트웨이 시간 초과
505 서버 오류 지원되지 않는 SIP 버전
600 전역 실패 모든 곳에서 사용 중
603 전역 실패 적용 안 함
604 전역 실패 어느 곳에도 없음
606 전역 실패 받아들일 수 없음

SIP 메시지 헤더

SIP 메시지의 시작 줄 다음에는 하나 이상의 헤더가 옵니다. 포함된 헤더는 메시지가 응답인지, 요청인지에 따라 다릅니다. 헤더는 RFC 3261, 'SIP: Session Initiation Protocol'에 정의되어 있습니다. (http://www.microsoft.com/windows/reskits/webresources/ 의 웹 리소스 페이지  참조)

표 9에 나온 것처럼 헤더는 일반, 요청, 응답 및 엔터티의 네 가지 범주로 구분됩니다. 일반 범주의 헤더는 요청 및 응답 메시지 모두에 사용할 수 있습니다.

표 9   SIP 헤더

일반 요청 응답 엔터티
Accept Authorization Allow Content-encoding
Accept-encoding Contact Proxy-authenticate Content-length
Accept-language Hide Retry-after Content-type
Call-ID Max-forwards Server  
Contact Organization Unsupported  
Cseq Priority Warning  
Date Proxy-authorization WWW-authenticate  
Encryption Proxy-require    
Expires Route    
From Require    
Record-route Response-key    
Time stamp Subject    
To User-agent    
Via      

Windows Messenger 세션에서 가져온 다음의 샘플 SIP 요청에서는 SIP 헤더가 강조 table시되어 있습니다.


SIP 메시지 본문은 SDP(Session Description Protocol)에 의해 정의됩니다.

SDP(Session Description Protocol) 맨 위로

SDP(Session Description Protocol)는 멀티미디어 회의를 알리고 설명하기 위한 IETF table준입니다. SIP 메시지 본문에는 SDP에 의해 정의된 바와 같이 세션 설명이 포함되어 있습니다. 세션 설명은 단일 세션 설명, 0개 이상의 시간 설명 및 0개 이상의 미디어 설명의 세 부분으로 구성됩니다. 세션 설명은 전체 회의나 모든 미디어 스트림에 적용되는 전역 특성을 포함하고, 시간 설명은 회의 시작, 중지 및 반복 시간 정보를 포함하며, 미디어 설명은 특정 미디어 스트림에 대한 세부 정보를 포함합니다. table 10에는 SDP 메시지의 각 부분에서 사용할 수 있는 SDP 유형과 관련 설명 값이 나열되어 있습니다.

표 10   SDP 설명

세션 시간 미디어
유형 유형 유형
v 프로토콜 버전 t 세션이 활성화되는 시간 m 미디어 이름 및 전송 주소
o 소유자/작성자 및 세션 식별자 r 0 이상의 반복 횟수 i 미디어 제목
s 세션 이름     c 연결 정보
i 세션 정보     b 대역폭 정보
u 설명 URI(Uniform Resource Identifier)     k 암호화 키
e 전자 메일 주소     a 0개 이상의 미디어 특성 줄
p 전화 번호        
c 연결 정보        
b 대역폭 정보        
z table준 시간대 조정        
a 0개 이상의 세션 특성 줄        

Windows Messenger 세션에서 가져온 다음의 샘플 SIP 요청 메시지에서는 SIP 메시지 본문이 강조 table시되어 있습니다.

출저(좀 지난 자료지만 SIP에 대한 대략적인 내용이해에 도움이 되었음):
http://www.microsoft.com/korea/technet/prodtechnol/winxppro/plan/rtcprot.mspx 

Posted by 초코송송이
l