소켓을 생성 방법을 이해하기 위해서는 프로토콜에 대한 개념이 필요하다. 프로토콜이란 두 개체간에 데이터를 주고 받는 방법에 대한 약속이다. 즉, "컴퓨터 상호간의 대화에 필요한 통신 규약" 이라고 우선은 정의 내릴수 있다.
소켓의 생성 소켓을 생성하기 위해서 리눅스 윈도우즈 공통으로 socket이란 함수를 사용하게 된다. socket 함수는 호출 시 시스템 내부적으로 소켓을 생성하고 그 소켓을 조작하기 위해 필요한 파일 디스크립터를 리턴하는 함수이다.
시스템 내부적으로 소켓을 생성한다는 의미는 호스트가 통신을 하기 위해 필요한 리소스(Re-source)를 할당하는 것을 의미한다.
domain : 생성할 소켓이 통신을 하기 위해 사용할 프로토콜 체계(Protocol Family)를 설정한다.
type : 소켓이 데이터를 전송하는데 있어서, 사용하게 되는 전송 타입을 설정해 준다.
protocol : 두 호스트간에 통신을 하는데 있어서 특정 프로토콜을 지정 하기위해 사용된다.
socket 함수 호출시 요구되는 세 개의 인자들이 각각 무엇을 의미하는지 상당히 애매하게 느껴진다. 따라서 각각에 대해 보다 자세히 살펴 보자.
프로토콜 체계(Protocol Family)
우선 프로토콜 체계에 대해 아래 표를 참고 하자.
여기서 PF_INET을 소켓의 첫 번째 인자로 전달하는 경우에 IPv4기반의 인터넷 프로토콜을 기본으로 하는 소켓을 생성할 것이다.
데이터를 주고 받는 환경이 달라지면 그에 맞는 포로토콜이 존재하기 마련이다. 이러한 모든 경우에 소켓은 좋은 통신 도구가 될 수 있다. 왜냐하면 소켓은 여러 환경에서 사용 될수 있도록 설계 되어 있기 때문이다. 따라서 소켓을 생성 할 때 환경을 고려하여 프로토콜 체계를 지정해 주면 그 환경에서 사용 가능한 소켓이 생성된다. 즉, 소켓은 모든 프로토콜을 수용할 수 있다는 뜻이 되는데 이를 두고 "소켓은 프로토콜에 독립적이다." 라고 표현한다.
정리해 보면, 소켓을 생성할 때에는 소켓이 사용될 환경을 고려하여 프로토콜을 설정해 줘야 한다. socket 함수의 첫 번째 인자 domain이 그러한 용도로 사용된다. 참고로 소켓은 반드시 네트워크를 통해서 통신을 할 때만 사용되는 것은 아니다. 유닉스 계열의 시스템에서 시스템 내부의 프로세스들끼리 통신을 하기 위한 용도로도 사용 될 수 있다. PF_LOCAL은 바로 이러한 경우에 선택할 수 있는 프로토콜 체계가 된다.
소켓의 타입
socket 함수의 두번째 인자로 소켓의 타입(Type)을 설정해야 한다. 여기서 의미하는 타입이란 데이터 전송 타입을 말하는 것이다. 프로토콜 체계가 정해졌다고 해서 데이터 전송 방법까지 완전히 결정된 것은 아니다. 이 말을 달리해 보면, 하나의 포로토콜 체계 안에서도 데이터를 전송하는 방법이 둘 이상 존재할 수 있다는 뜻이 된다. 여기서 대표적인 전송 방식 두가지를 소개하겠다.
- SOCK_STREM(연결 지향형 소켓)
1. 에러나 데이터의 손실 없이 무사히 전달된다. 독립된 전송 라인을 통하여 데이터를 전달하기 때문에 라인상에 문제만 없다면, 데이터가 반드시 전달된다는 것을 보장 받을수 있다. 또한 하나의 라인이 존재한다는 것은 반드시 호스트 대 호스트의 연결은 1 대 1 이어야 한다는 것을 의미한다. 즉, 데이터를 보내는 곳이 한 곳인데, 받는 곳이 둘 이상이 될 수 없다.
2. 전송하는 순서대로 전달된다. 전송 라인이 하나이기 때문에 뒤에 보낸 데이터가 이전에 보내진 데이터보다 일찍 도착 할 수는 없을 것이다.
3. 전송되는 데이터의 경계(Boundary)가 존재하지 않는다. 호스트 대 호스트가 연결 지향 소켓을 생성해서 통신을 하는 경우, 두 번의 write 함수 호출을 통해서 데이터를 전송했다 하더라도, 수신측 호스트의 버퍼가 넉넉하다면 한번의 read 함수 호출을 통해서 모든 데이터를 수신할 수 있다.
또한, 반대로 한번의 write 함수 호출을 통해서 데이터가 전송되었다 하더라도, 서너 번의 read 함수 호출을 통해서 데이터를 조금씩 나누어 수신할 수도 있다.
지금까지 SOCK_STREAM의 특징들을 살펴 보았는데, 한마디로 압축해 보면 "신뢰성 있는 순차적인 바이트 기반의 연결 지향 전송 타입"이라 할 수 있다.
- SOCK_DGRAM(비연결 지향형 소켓)
1. 전송되는 순서에 상관없이 가장 빠른 전송을 지향한다. 각각의 데이터가 빠른 경로를 찾아 전송이 되므로 먼저 전송된 데이터가 유리하지만 항상 빠른것은 아니다.
2. 전송되는 데이터는 손실될 수도 있고 에러가 발생할 수도 있다.
3. 전송되는 데이터의 경계(Boundary)가 존재한다. 데이터를 전송하는 호스트가 세 번의 함수 호출을 통해서 데이터를 전송했다면, 수신하는 호스트도 반드시 세번의 함수 호출을 거쳐야 데이터를 완전히 수신할 수 있게 된다. 데이터의 경계가 없었던 SOCK_STREAM 타입과 대조를 이룬다.
4. 한번에 전송되는 데이터의 크기는 제한된다. 비연결 지향형 소켓을 기반으로 데이터를 전송할 경우 호스트가 한번에 전송하는 데이터의 크기는 제한될 수 밖에 없다. 따라서 그 크기가 크다면 적절히 데이터를 나누어야 한다.
정리해 보면, 비연결 지향형 소켓의 경우 빠른 정송을 위해 최선을 다하지만, 경우에 따라서 데이터의 손실이 있을 수도 있으며, 전송되는 데이터의 크기가 제한되어 있기 때문에 덩치가 큰 데이터를 전송할 경우 나누어서 보내야 한다.
프로토콜의 선택
세번째 인자로 전달되는 protocol은 호스트 대 호스트가 사용할 프로토콜을 설정하기 위해 사용된다. 그런데 지금까지 우리는 프로토콜 체계에 대해서, 그리고 소켓의 데이터 전송 타입에 대해서도 살펴보았다. 그런데 또 다시 프로토콜을 설정한다고 하니 의아할 수도 있겠다. 일단 인자로 전달할 수 있는 상수에 대해 살펴보도록 하자. 프로토콜 체계가 PF_INET인 경우 다음과 같은 값이 올 수 있다.
- IPPROTO_TCP : TCP를 기반으로 하는 소켓을 생성.
- IPPROTO_UDP : UDP를 기반으로 하는 소켓을 생성.
TCP 소켓이란 인터넷을 기반으로 하는 연결 지향형 소켓을 의미한다. 또한 UDP 소켓이란 인터넷을 기반으로 하는 비연결 지향형 소켓을 의미한다.
따라서 TCP 소켓을 생성하기 위해서는 socket 함수의 세번째 인자로 IPPROTO_TCP를, UDP 소켓을 생성하기 위해서는 IPPROTO_UDP를 전달해야 한다.
하지만 우리는 이미 두번째 인자를 전달하면서 인터넷 기반 연결 지향 소켓인지, 비연결 지향 소켓인지를 결정 지었다.(그렇기 때문에 인자 값에 0을 넣어 줘도 알아서 우리가 원하는 소켓을 생성해 준다.) 그런데 세번째 인자를 또 다시 전달하는 이유는 다음과 같다.
예를 들어, 하나의 프로토콜 체계 안에서 데이터 전송 타입까지 같으면서도 최종적으로 통신하는 형태가 다른(즉 전송 타입은 같지만 그 안에서도 프로토콜이 또 다시 나뉘는 상황을 말함) 여러개의 프로토콜이 존재하는 경우에는, 이 세번째 인자가 유용한 인자가 된다. 즉, 세번째 인자는 프로토콜을 조금 더 구체화 하기 위해서 사용된다.
지금까지의 내용을 정리해 보면 socket 함수에 전달할 수 있는 인자의 종류는 프로토콜 체계가 PF_INET인 경우 다음과 같이 두 가지로 정리해서 말할 수 있다.
즉, 프로토콜 체계가 PF_INET이면서 데이터 전송 타입이 SOCK_STREAM인 경우 선택할 수 있는 프로토콜은 오직 하나 IPPROTO_TCP이며, 이 경우 생성되는 소켓을 TCP소켓이라 한다. (Case 1)
또한, PF_INET이면서 SOCK_DGRAM인 경우에 선택할 수 있는 프로토콜도 오직하나 IPPROTO_UDP뿐이며 이 경우에 생성되는 소켓을 UDP 소켓이라 한다. (Case 2)
소켓의 생성 소켓을 생성하기 위해서 리눅스 윈도우즈 공통으로 socket이란 함수를 사용하게 된다. socket 함수는 호출 시 시스템 내부적으로 소켓을 생성하고 그 소켓을 조작하기 위해 필요한 파일 디스크립터를 리턴하는 함수이다.
시스템 내부적으로 소켓을 생성한다는 의미는 호스트가 통신을 하기 위해 필요한 리소스(Re-source)를 할당하는 것을 의미한다.
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
성공 시 파일 디스크립터, 실패 시 -1을 리턴
domain : 생성할 소켓이 통신을 하기 위해 사용할 프로토콜 체계(Protocol Family)를 설정한다.
type : 소켓이 데이터를 전송하는데 있어서, 사용하게 되는 전송 타입을 설정해 준다.
protocol : 두 호스트간에 통신을 하는데 있어서 특정 프로토콜을 지정 하기위해 사용된다.
socket 함수 호출시 요구되는 세 개의 인자들이 각각 무엇을 의미하는지 상당히 애매하게 느껴진다. 따라서 각각에 대해 보다 자세히 살펴 보자.
프로토콜 체계(Protocol Family)
우선 프로토콜 체계에 대해 아래 표를 참고 하자.
프로토콜 체계(Protocol Family) 정의
PF_INET IPv4 인터넷 프로토콜
PF_INET6 IPv6 인터넷 프로토콜
PF_LOCAL Local 통신을 위한 UNIX 프로토콜
PF_PACKET Low level socket을 위한 인터페이스
PF_IPX IPX 노벨 프로토콜
PF_INET IPv4 인터넷 프로토콜
PF_INET6 IPv6 인터넷 프로토콜
PF_LOCAL Local 통신을 위한 UNIX 프로토콜
PF_PACKET Low level socket을 위한 인터페이스
PF_IPX IPX 노벨 프로토콜
여기서 PF_INET을 소켓의 첫 번째 인자로 전달하는 경우에 IPv4기반의 인터넷 프로토콜을 기본으로 하는 소켓을 생성할 것이다.
데이터를 주고 받는 환경이 달라지면 그에 맞는 포로토콜이 존재하기 마련이다. 이러한 모든 경우에 소켓은 좋은 통신 도구가 될 수 있다. 왜냐하면 소켓은 여러 환경에서 사용 될수 있도록 설계 되어 있기 때문이다. 따라서 소켓을 생성 할 때 환경을 고려하여 프로토콜 체계를 지정해 주면 그 환경에서 사용 가능한 소켓이 생성된다. 즉, 소켓은 모든 프로토콜을 수용할 수 있다는 뜻이 되는데 이를 두고 "소켓은 프로토콜에 독립적이다." 라고 표현한다.
정리해 보면, 소켓을 생성할 때에는 소켓이 사용될 환경을 고려하여 프로토콜을 설정해 줘야 한다. socket 함수의 첫 번째 인자 domain이 그러한 용도로 사용된다. 참고로 소켓은 반드시 네트워크를 통해서 통신을 할 때만 사용되는 것은 아니다. 유닉스 계열의 시스템에서 시스템 내부의 프로세스들끼리 통신을 하기 위한 용도로도 사용 될 수 있다. PF_LOCAL은 바로 이러한 경우에 선택할 수 있는 프로토콜 체계가 된다.
소켓의 타입
socket 함수의 두번째 인자로 소켓의 타입(Type)을 설정해야 한다. 여기서 의미하는 타입이란 데이터 전송 타입을 말하는 것이다. 프로토콜 체계가 정해졌다고 해서 데이터 전송 방법까지 완전히 결정된 것은 아니다. 이 말을 달리해 보면, 하나의 포로토콜 체계 안에서도 데이터를 전송하는 방법이 둘 이상 존재할 수 있다는 뜻이 된다. 여기서 대표적인 전송 방식 두가지를 소개하겠다.
- SOCK_STREM(연결 지향형 소켓)
1. 에러나 데이터의 손실 없이 무사히 전달된다. 독립된 전송 라인을 통하여 데이터를 전달하기 때문에 라인상에 문제만 없다면, 데이터가 반드시 전달된다는 것을 보장 받을수 있다. 또한 하나의 라인이 존재한다는 것은 반드시 호스트 대 호스트의 연결은 1 대 1 이어야 한다는 것을 의미한다. 즉, 데이터를 보내는 곳이 한 곳인데, 받는 곳이 둘 이상이 될 수 없다.
2. 전송하는 순서대로 전달된다. 전송 라인이 하나이기 때문에 뒤에 보낸 데이터가 이전에 보내진 데이터보다 일찍 도착 할 수는 없을 것이다.
3. 전송되는 데이터의 경계(Boundary)가 존재하지 않는다. 호스트 대 호스트가 연결 지향 소켓을 생성해서 통신을 하는 경우, 두 번의 write 함수 호출을 통해서 데이터를 전송했다 하더라도, 수신측 호스트의 버퍼가 넉넉하다면 한번의 read 함수 호출을 통해서 모든 데이터를 수신할 수 있다.
또한, 반대로 한번의 write 함수 호출을 통해서 데이터가 전송되었다 하더라도, 서너 번의 read 함수 호출을 통해서 데이터를 조금씩 나누어 수신할 수도 있다.
지금까지 SOCK_STREAM의 특징들을 살펴 보았는데, 한마디로 압축해 보면 "신뢰성 있는 순차적인 바이트 기반의 연결 지향 전송 타입"이라 할 수 있다.
- SOCK_DGRAM(비연결 지향형 소켓)
1. 전송되는 순서에 상관없이 가장 빠른 전송을 지향한다. 각각의 데이터가 빠른 경로를 찾아 전송이 되므로 먼저 전송된 데이터가 유리하지만 항상 빠른것은 아니다.
2. 전송되는 데이터는 손실될 수도 있고 에러가 발생할 수도 있다.
3. 전송되는 데이터의 경계(Boundary)가 존재한다. 데이터를 전송하는 호스트가 세 번의 함수 호출을 통해서 데이터를 전송했다면, 수신하는 호스트도 반드시 세번의 함수 호출을 거쳐야 데이터를 완전히 수신할 수 있게 된다. 데이터의 경계가 없었던 SOCK_STREAM 타입과 대조를 이룬다.
4. 한번에 전송되는 데이터의 크기는 제한된다. 비연결 지향형 소켓을 기반으로 데이터를 전송할 경우 호스트가 한번에 전송하는 데이터의 크기는 제한될 수 밖에 없다. 따라서 그 크기가 크다면 적절히 데이터를 나누어야 한다.
정리해 보면, 비연결 지향형 소켓의 경우 빠른 정송을 위해 최선을 다하지만, 경우에 따라서 데이터의 손실이 있을 수도 있으며, 전송되는 데이터의 크기가 제한되어 있기 때문에 덩치가 큰 데이터를 전송할 경우 나누어서 보내야 한다.
프로토콜의 선택
세번째 인자로 전달되는 protocol은 호스트 대 호스트가 사용할 프로토콜을 설정하기 위해 사용된다. 그런데 지금까지 우리는 프로토콜 체계에 대해서, 그리고 소켓의 데이터 전송 타입에 대해서도 살펴보았다. 그런데 또 다시 프로토콜을 설정한다고 하니 의아할 수도 있겠다. 일단 인자로 전달할 수 있는 상수에 대해 살펴보도록 하자. 프로토콜 체계가 PF_INET인 경우 다음과 같은 값이 올 수 있다.
- IPPROTO_TCP : TCP를 기반으로 하는 소켓을 생성.
- IPPROTO_UDP : UDP를 기반으로 하는 소켓을 생성.
TCP 소켓이란 인터넷을 기반으로 하는 연결 지향형 소켓을 의미한다. 또한 UDP 소켓이란 인터넷을 기반으로 하는 비연결 지향형 소켓을 의미한다.
따라서 TCP 소켓을 생성하기 위해서는 socket 함수의 세번째 인자로 IPPROTO_TCP를, UDP 소켓을 생성하기 위해서는 IPPROTO_UDP를 전달해야 한다.
하지만 우리는 이미 두번째 인자를 전달하면서 인터넷 기반 연결 지향 소켓인지, 비연결 지향 소켓인지를 결정 지었다.(그렇기 때문에 인자 값에 0을 넣어 줘도 알아서 우리가 원하는 소켓을 생성해 준다.) 그런데 세번째 인자를 또 다시 전달하는 이유는 다음과 같다.
예를 들어, 하나의 프로토콜 체계 안에서 데이터 전송 타입까지 같으면서도 최종적으로 통신하는 형태가 다른(즉 전송 타입은 같지만 그 안에서도 프로토콜이 또 다시 나뉘는 상황을 말함) 여러개의 프로토콜이 존재하는 경우에는, 이 세번째 인자가 유용한 인자가 된다. 즉, 세번째 인자는 프로토콜을 조금 더 구체화 하기 위해서 사용된다.
지금까지의 내용을 정리해 보면 socket 함수에 전달할 수 있는 인자의 종류는 프로토콜 체계가 PF_INET인 경우 다음과 같이 두 가지로 정리해서 말할 수 있다.
Case Domain Type Protocol
1 PF_INET SOCK_STREAM IPPROTO_TCP(0)
2 PF_INET SOCK_DGRAM IPPROTO_UDP(0)
1 PF_INET SOCK_STREAM IPPROTO_TCP(0)
2 PF_INET SOCK_DGRAM IPPROTO_UDP(0)
즉, 프로토콜 체계가 PF_INET이면서 데이터 전송 타입이 SOCK_STREAM인 경우 선택할 수 있는 프로토콜은 오직 하나 IPPROTO_TCP이며, 이 경우 생성되는 소켓을 TCP소켓이라 한다. (Case 1)
또한, PF_INET이면서 SOCK_DGRAM인 경우에 선택할 수 있는 프로토콜도 오직하나 IPPROTO_UDP뿐이며 이 경우에 생성되는 소켓을 UDP 소켓이라 한다. (Case 2)
'Study > TCP/IP' 카테고리의 다른 글
주소 정보의 표현 (0) | 2008.02.16 |
---|---|
Port란, (0) | 2008.02.16 |
Internet Address (0) | 2008.02.16 |
파일 조작하기 (0) | 2008.02.16 |
네트워크 프로그래밍의 이해 (0) | 2008.02.16 |