11.3절: 글로벌 IP 인터넷 (The Global IP Internet)
글로벌 IP 인터넷은 가장 널리 알려진 인터넷의 구현체이며, 1969년부터 존재해 왔다. 내부 구조는 복잡하고 지속적으로 변화하고 있지만, 클라이언트-서버 응용 프로그램의 조직 방식은 1980년대 초부터 놀라울 정도로 안정적으로 유지되어 왔다.
각 인터넷 호스트는 TCP/IP 프로토콜을 구현하는 소프트웨어를 실행한다. 이 프로토콜은 거의 모든 현대 시스템에서 지원된다. 클라이언트와 서버는 소켓 인터페이스 함수와 Unix I/O 함수를 조합하여 통신한다. IP는 이름 지정 체계와 패킷 전송 메커니즘을 제공하며, TCP는 이 위에 구축되어 신뢰할 수 있는 양방향 연결을 제공한다. 이 절에서는 TCP/IP를 단일 프로토콜처럼 간단화하여 설명하며, UDP는 다루지 않는다.
프로그래머 관점에서 인터넷은 다음과 같은 속성을 지닌 전 세계적인 호스트 집합으로 생각할 수 있다:
- 호스트들은 32비트 IP 주소에 매핑된다.
- 이 IP 주소는 인터넷 도메인 이름에 다시 매핑된다.
- 하나의 호스트의 프로세스는 다른 호스트의 프로세스와 연결을 통해 통신할 수 있다.
11.3.1절: IP 주소 (IP Addresses)
IP 주소는 부호 없는 32비트 정수이며, 구조체 struct in_addr로 저장된다. 다음은 그 정의이다:
struct in_addr {
uint32_t s_addr; // 네트워크 바이트 순서의 주소 (big-endian)
};
초기의 소켓 구현의 유산으로 인해 스칼라 값을 구조체에 저장하는 방식이 남아있지만, 이것은 바람직하지 않다. IP 주소는 네트워크를 통해 전송되는 데이터이므로 TCP/IP는 항상 big-endian 바이트 순서를 사용한다.
빅 엔디안, 리틀 엔디안
빅 엔디안(big-endian)과 리틀 엔디안(little-endian)은 멀티바이트 데이터를 메모리에 저장하거나 전송할 때 바이트 순서를 어떻게 배치할지를 결정하는 규칙이다. 특히 IP 주소와 같은 네트워크 데이터는 항상 빅 엔디안 방식으로 처리된다.
1. 빅 엔디안 (Big-endian)
- 가장 큰 바이트(상위 바이트)를 가장 먼저(작은 주소)에 저장한다.
- 사람이 읽는 숫자 표기 방식과 유사하다.
- 예: 0x12345678 이라는 4바이트 정수를 메모리에 저장하면 다음과 같다 (주소가 증가하는 순서):
주소: 0x00 0x01 0x02 0x03
값: 0x12 0x34 0x56 0x78
- 네트워크 프로토콜(TCP/IP)은 항상 빅 엔디안으로 데이터를 주고받는다. 이를 network byte order라고 부른다.
2. 리틀 엔디안 (Little-endian)
- 가장 작은 바이트(하위 바이트)를 가장 먼저(작은 주소)에 저장한다.
- 인텔 x86-64 시스템이 사용하는 방식이다.
- 같은 값 0x12345678을 저장하면:
주소: 0x00 0x01 0x02 0x03
값: 0x78 0x56 0x34 0x12
3. 왜 변환이 필요한가?
호스트 시스템이 리틀 엔디안이라면, IP 주소를 네트워크를 통해 보낼 때 htonl() (host-to-network long) 같은 함수를 써서 빅 엔디안 형식으로 변환해야 한다. 반대로, 네트워크에서 받은 데이터를 사용할 때는 ntohl() (network-to-host long) 함수로 다시 호스트 바이트 순서로 변환해야 한다.
다음 함수들을 통해 호스트 바이트 순서와 네트워크 바이트 순서 간 변환을 수행한다:
uint32_t htonl(uint32_t hostlong); // host → network (32bit)
uint16_t htons(uint16_t hostshort); // host → network (16bit)
uint32_t ntohl(uint32_t netlong); // network → host (32bit)
uint16_t ntohs(uint16_t netshort); // network → host (16bit)
사람이 보기 쉬운 형태로는 IP 주소를 점-10진수(dotted-decimal)로 표현한다. 예를 들어 128.2.194.242는 0x8002c2f2에 해당한다. 리눅스에서는 hostname -i 명령으로 자신의 호스트 IP 주소를 확인할 수 있다.
또한 다음 함수들을 사용하여 점-10진수 문자열과 이진 IP 주소 간 변환이 가능하다:
int inet_pton(AF_INET, const char *src, void *dst); // 문자열 → 바이너리
const char *inet_ntop(AF_INET, const void *src, char *dst, socklen_t size); // 바이너리 → 문자열
여기서 n은 network, p는 presentation을 의미한다. 이 함수들은 IPv4와 IPv6 모두에 적용 가능하지만, 이 책에서는 IPv4 만 다룬다.
11.3.2절: 인터넷 도메인 이름 (Internet Domain Names)
클라이언트와 서버는 서로 통신할 때 IP 주소를 사용한다. 하지만 숫자로 된 긴 IP 주소는 사람이 기억하거나 사용하기 어렵다. 그래서 인터넷은 보다 사람이 친숙하게 사용할 수 있는 도메인 이름 체계와, 이 이름을 IP 주소로 변환하는 매커니즘을 정의한다.
도메인 이름은 예를 들어 whaleshark.ics.cs.cmu.edu처럼, 단어(문자, 숫자, 하이픈)들을 점(.)으로 구분하여 구성된다. 이 이름들은 트리 구조의 계층적 체계로 구성되며, 각 이름은 트리 내 위치를 인코딩한다.
도메인 이름 계층 구조
- 루트는 이름이 없는 노드로 시작한다.
- 그 아래는 ICANN(Internet Corporation for Assigned Names and Numbers)이 관리하는 최상위 도메인(TLD, Top-Level Domains)이 있다: 예) com, edu, gov, org, net 등
- 그다음은 기관마다 할당되는 2차 도메인이다: 예) cmu.edu
- 기관은 그 아래의 3차, 4차 도메인을 자유롭게 구성할 수 있다: 예) cs.cmu.edu, whaleshark.ics.cs.cmu.edu 등
이 계층 구조는 트리로 표현되며, 각 노드는 상위 노드 경로를 따라 이름이 완성된다.
DNS: 도메인 이름 시스템
초기에는 도메인 이름과 IP 주소의 매핑을 하나의 텍스트 파일(HOSTS.TXT)에 수작업으로 기록했지만, 1988년부터는 전 세계적으로 분산된 데이터베이스 시스템인 DNS(Domain Name System)가 이를 담당하게 되었다.
DNS 데이터베이스는 수백만 개의 호스트 항목으로 구성되며, 각 항목은 하나 이상의 도메인 이름과 IP 주소의 매핑을 정의한다. 수학적으로 보면, 도메인 이름과 IP 주소가 동치 클래스(equivalence class)를 형성하는 셈이다.
리눅스의 nslookup 명령을 이용하면 도메인 이름에 대응되는 IP 주소를 쉽게 조회할 수 있다. 예를 들어 twitter.com은 네 개의 IP 주소에 매핑되는 것을 확인할 수 있다.
11.3.3절: 인터넷 연결 (Internet Connections)
인터넷에서 클라이언트와 서버는 바이트 스트림(byte stream)을 주고받는 연결(connection)을 통해 통신한다. 이 연결은 다음과 같은 특성을 가진다:
- 점대점(point-to-point): 두 프로세스 간의 직접 연결이다.
- 전이중(full-duplex): 양방향으로 동시에 데이터가 흐를 수 있다.
- 신뢰성(reliable): 치명적인 장애(예: 네트워크 케이블 절단)를 제외하면, 송신된 바이트는 수신 측에서 동일한 순서로 모두 도착한다.
소켓 (Socket)
소켓은 연결의 종단점이다. 각각의 소켓은 인터넷 주소와 16비트 포트 번호(port number)를 포함한 소켓 주소(socket address)를 가진다. 이 주소는 일반적으로 address:port 형식으로 표기된다.
- 클라이언트 소켓 포트 번호는 커널에 의해 자동으로 할당되며, 이를 ephemeral port (일시적 포트)라고 한다.
- 서버 소켓 포트 번호는 일반적으로 고정된 well-known port이다. 예를 들면:
- 웹 서버: 포트 80
- 이메일 서버: 포트 25
각 서비스는 well-known service name을 가지며, 예를 들어 http는 포트 80, smtp는 포트 25와 매핑된다. 이 매핑 정보는 리눅스 시스템의 /etc/services 파일에 저장되어 있다.
'크래프톤 정글 (컴퓨터 시스템: CSAPP) > 11장 네트워크 프로그래밍' 카테고리의 다른 글
컴퓨터 시스템 : CSAPP 11장 정리 - 11.6 종합설계 :소형 웹 서버 Part.2 (2) | 2025.05.03 |
---|---|
컴퓨터 시스템 : CSAPP 11장 정리 - 11.6 종합설계 :소형 웹 서버 Part.1 (0) | 2025.05.03 |
컴퓨터 시스템 : CSAPP 11장 정리 - 11.5 웹 서버 이론편 (0) | 2025.05.03 |
컴퓨터 시스템 : CSAPP 11장 정리 - 11.4 소켓 인터페이스 (0) | 2025.05.02 |
컴퓨터 시스템 : CSAPP 11장 정리 - 11.1 ~ 11.2 (1) | 2025.05.02 |