layered
2 소켓의 타입과 프로토콜의 설정 본문
프로토콜 Protocol
컴퓨터 상호간의 대화에 필요한 통신규약.
이렇게 말하면 조금 모호한 면이 있을 것이다. 간단하게 다음과 같은 상황이 있다고 생각해 보자.
컴퓨터들이 서로 통신을 하려고 한다.
몇 가지 물음표가 떠오를 것이다.
- What is communicated
- How it is communicated
- When it is communicated
이런 것들을 상호간에 정하는 게 바로 프로토콜이다!
이제 소켓을 생성하는 함수를 다시 살펴보자.
int socket(int domain, int type, int protocol);
SOCKET socket(int af, int type, int procotol);
domain, af
소켓이 사용할 프로토콜 체계(Protocol Family) 정보를 전달하는 부분이다.
간단하게 말하면 프로토콜의 분류를 나타낸다고 보면 된다.
여기에서 넘겨 준 프로토콜 체계에 따라, 최종 프로토콜의 정보를 나타내는 세 번째 인자가 결정된다.
이름 | 프로토콜 체계 |
PF_INET | IPv4 인터넷 프로토콜 체계 |
PF_INET6 | IPv6 인터넷 프로토콜 체계 |
PF_LOCAL | 로컬 통신을 위한 UNIX 프로토콜 체계 |
PF_PACKET | Low Level 소켓을 위한 프로토콜 체계 |
PF_IPX | IPX 노벨 프로토콜 체계 |
그런데 윈속의 소켓 생성 함수를 보면 어쩐지 PF와는 조금 다른데 이는 주소 체계로, 프로토콜 체계처럼 주소의 분류를 나타내는 것이다. 그런데 또 헤더 파일을 보면 PF와 AF는 같은 값을 가진다.
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_INET AF_INET
#define PF_IPX AF_IPX
#define PF_INET6 AF_INET6
// 등등
그래서 둘을 혼용해서 쓰는 건 실질적으로는 문제가 없지만, 의미적으로 구분해서 쓰는 게 좋다고 한다.
프로토콜 체계는 소켓을 생성할 때, 주소 체계는 주소 구조체를 초기화할 때.
메모
찾아 보니 소켓 인터페이스의 원래 개념은 하나의 프로토콜 체계가 여러 개의 주소를 가질 수 있다는 것이어서, 주소 체계를 따로 구분해 두고 사용하도록 했다고 한다. 그런데 막상 보니 그런 경우가 딱히 없고, 실질적인 정의도 같다 보니 섞여서 쓰이고 있는 것이라고 한다.
사실 이해가 잘 안 되어서 그냥 써 두기만 했다... 일단은 프로토콜 체계를 파라미터로 넘겨 준다는 것만 기억하고 넘어가야겠다.
type
소켓의 타입은 소켓의 데이터 전송 방식을 의미하며, 네트워크 프로토콜의 종류에 따라 달라진다.
대표적으로 두 가지가 있다.
1 SOCK_STREAM
"저기... 데이터 좀 보내도 되나요?"
연결지향형 소켓으로, 경로를 확보해 두고 수신자의 상황을 판단해 가면서 데이터를 전송한다.
따라서 전송되는 데이터의 경계가 없고 신뢰성을 보장하며, 전송한 순서대로 데이터가 수신된다.
2 SOCK_DGRAM
"데이터 보낼게요!"
비 연결지향형 소켓으로, 그냥 냅다 보내기 때문에 속도는 빠르지만 손실되거나 뒤죽박죽 전송될 우려가 있다.
또한 한번에 보낼 수 있는 데이터의 크기가 제한되어 있어서 데이터의 경계가 존재한다.
주로 다루는 것이 인터넷 프로토콜임을 생각할 때, 위의 소켓 타입으로 결정되는 프로토콜은 각각 TCP와 UDP이다.
여기까지 종합해 보면 첫 번째 파라미터인 PF를 통해 프로토콜의 분류를 설정하고, 두 번째 파라미터인 type으로는 그 분류 내에서 사용할 프로토콜을 지정하는 것이라고 할 수 있다.
protocol
사용할 프로토콜을 지정한다. 하나의 프로토콜 체계 안에 데이터의 전송 방식(= 소켓 타입)이 동일한 프로토콜이 여러 개 있을 경우, 앞선 두 개의 파라미터로는 구분할 수 없기 때문이다.
TCP나 UDP의 경우는 상관이 없기 때문에 그냥 0을 넣기도 하지만, 굳이 명시하고자 한다면 IPPROTO_TCP나 IPPROTO_UDP를 사용하면 된다.
간단한 소켓 생성 코드!
int main() {
WSADATA wsadata;
if (WSAStartup(MAKEWORD(2, 2), &wsadata))
return 1;
printf("윈속 초기화!\n");
SOCKET sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
return 1;
printf("소켓 생성!\n");
closesocket(sock);
WSACleanup();
return 0;
}
'네트워크 > 열혈 TCP IP 소켓 프로그래밍' 카테고리의 다른 글
5 TCP 기반 서버/클라이언트 2 (0) | 2023.05.01 |
---|---|
간단한 서버/클라이언트 구현 (0) | 2023.05.01 |
4 TCP 기반 서버/클라이언트 1 (0) | 2023.04.30 |
3 주소 체계와 데이터 정렬 (0) | 2023.04.29 |
1 네트워크 프로그래밍과 소켓의 이해 (1) | 2023.04.27 |