프로토콜 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 |