[CSAPP] 11장 네트워크 프로그래밍 Network Programming (1/4)
출처
Randal E. Bryant & David R. O'Hallaron. (2015). Computer Systems: A Programmer's Perspective (3rd ed.). Pearson.
1. 클라이언트-서버 프로그래밍 모델
모든 네트워크 애플리케이션은 클라이언트-서버 모델에 기반을 두고 있다.
애플리케이션은 서버 프로세스와 하나 이상의 클라이언트 프로세스로 이루어져 있다.
서버는 리소스를 관리하고 조작하여 클라이언트에게 서비스를 제공한다.
<예시>
- 웹 서버는 클라이언트를 위해서 디스크 파일들을 회수하고 실행시킨다.
- FTP 서버는 클라이언트를 위해 디스크 파일들을 회수하고 저장한다.
- 이메일 서버는 클라이언트를 위해 spool 파일들을 읽고 업데이트한다.
클라이언트-서버 모델에서 기본 작업은 트랜잭션 transaction (DB의 원자성을 가진 트랜잭션과 다른 개념이다.)이다.
클라이언트-서버 트랜잭션은 4개의 단계로 이루어져 있다.
- 클라이언트가 서비스가 필요할 때, 클라이언트는 서버에게 요청 request를 보냄으로써 거래를 시작한다.
<예시> 웹 브라우저가 파일이 필요할 때, 웹 브라우저는 웹 서버에게 요청을 보낸다. - 서버가 요청을 받고, 요청을 해석하고, 적절한 방법으로 자신의 리소스를 조작한다.
<예시> 웹 서버가 브라우저로부터 요청을 받으면, 웹 서버는 디스크 파일을 읽는다. - 서버는 클라이언트에게 응답 response을 보내고 다음 요청을 기다린다.
<예시> 웹 서버는 클라이언트에게 파일을 보낸다. - 클라이언트는 응답을 받고 응답을 조작한다.
<예시> 웹 브라우저가 서버로부터 페이지를 응답받으면 그것을 스크린에 나타낸다.
2. 네트워크
클라이언트와 서버는 같은 호스트에서 실행될 수도 있지만 주로 별개의 호스트에서 실행된다.
클라이언트와 서버는 서로 통신하기 위해 컴퓨터 네트워크의 하드웨어와 소프트웨어 자원을 사용한다.
호스트에게 네트워크란 그저 데이터 송수신기 역할을 하는 또 하나의 I/O 디바이스일 뿐이다. UNIX에서 네트워크는 가상 디스크처럼 다뤄진다.
네트워크 어댑터는 I/O 버스에 있는 확장 슬롯에 플러그되어 있어 있다. 네트워크를 위한 물리 인터페이스를 제공한다.
네트워크로부터 데이터를 받으면, 데이터는 어댑터로부터 I/O 버스와 메모리 버스를 지나 메인 메모리로 복사된다. 이는 일반적으로 DMA 전송으로 복사된다. 비슷하게, 데이터는 메모리에서 네트워크로 복사될 수도 있다.
네트워크는 지리적 인접성에 따라 계층적으로 조직되어 있다.
(1) 하나의 LAN, Ethernet 세그먼트
네트워크 계층에서 가장 낮은 레벨은 LAN (Local Area Network)이다. 가장 인기 있는 LAN 기술은 지금까지 Ethernet이다. Ethernet은 1970년대 중반에 Xerox PARC에서 개발되었다. Ethernet은 상당히 회복력이 좋다(주: 네트워크 충돌이나 장애 상황에서도 데이터 전송이 가능하도록 설계된 알고리즘 CSMA/CD 등을 사용한다.)고 증명되어 있다.
Ethernet 세그먼트는 몇몇 전선 (일반적으로 꼬여 있는 한 쌍의 전선)과 허브 hub라고 불리는 작은 박스로 이루어져 있다.
전선
- 각각의 전선은 동일한 최대 비트 대역폭 bit bandwidth를 가진다. 일반적으로 100Mb/s 또는 1Gb/s이다.
- 전선의 한쪽 끝은 호스트에 있는 어댑터에 연결되어 있고, 나머지 한쪽은 허브에 있는 포트에 연결되어 있다.
허브
허브는 각 포트에서 비트를 받아서 다른 포트들로 복사한다. 이에 따라 모든 호스트는 모든 비트를 볼 수 있게 된다.
호스트의 Ethernet 어댑터
Ethernet 어댑터는 전역적으로 고유한 48 비트 주소를 가진다. (MAC 주소) 이 주소는 어댑터의 비휘발성 메모리에 저장되어 있다.
호스트는 Ethernet 세그먼트에 있는 다른 호스트들에게 프레임 frame이라고 불리는 비트의 덩어리를 전송할 수 있다. 각각의 프레임은 고정된 길이의 헤더 비트를 가지고 있다. 헤더 비트에는 프레임의 출발지 source와 도착지 destination, 그리고 프레임의 길이를 나타내는 부분이 있다. 헤더 뒤에는 페이로드 payload 데이터 비트가 온다.
모든 호스트 어댑터들은 이 프레임을 볼 수 있지만, 도착지의 호스트만이 이 프레임을 읽어들인다.
(2) 여러 개의 Ethernet 세그먼트, 브릿지형 이더넷
Ethernet 세그먼트는 일반적으로 작은 방이나 건물의 한 층과 같이 작은 지역에 퍼져 있다. 여러 개의 Ethernet 세그먼트는 더 큰 LAN들에 연결될 수 있다. 이렇게 구성된 더 큰 LAN은 브릿지형 이더넷 bridged Ethernet라고 불린다. 브릿지형 이더넷은 건물 전체나 캠퍼스 전체에 퍼져 있을 수 있다.
브릿지형 Ethernet은 전선들과 브릿지 bridges라고 불리는 작은 박스들을 사용한다.
전선
- 어떤 전선은 브릿지와 브릿지를 연결하고, 다른 어떤 전선은 브릿지와 허브를 연결한다.
- 전선의 대역폭은 서로 다를 수 있다.
<예시> 브릿지와 브릿지를 연결하는 전선은 1Gb/s 대역폭을 가지고, 브릿지와 허브를 연결하는 전선은 100 Mb/s의 대역폭을 가질 수 있다.
브릿지
브릿지들은 허브보다 전선 대역폭을 더 효율적으로 활용한다.
기발한 분산 알고리즘 distributed algorithm을 사용해서, 브릿지들은 어떤 포트에서 어떤 호스트가 접근 가능한지를 자동으로 장기간에 걸쳐 학습한다. 그리고 포트에서 포트로의 프레임 복사를 필요한 경우에만 선택적으로 진행한다.
<예시>
- 호스트 A가 같은 세그먼트에 있는 호스트 B로 프레임을 전송하는 경우
=> 브릿지 X는 자신의 입력 포트에 도착한 프레임을 버린다. 다른 세그먼트에 있는 대역폭을 절약하기 위해서이다.
- 호스트 A가 다른 세그먼트에 있는 호스트 C에게 프레임을 전송하는 경우
=> 브릿지 X는 브릿지 Y의 포트에만 프레임을 복사한다. 브릿지 Y의 포트는 호스트 C가 있는 세그먼트와 연결된 포트로만 프레임을 복사할 것이다.
(3) WAN
LAN 이미지를 간단하게 그리면 다음과 같다. 허브와 브리지, 그리고 이들을 연결하는 전선을 하나의 수평선에 그렸다.
네트워크 계층에서 LAN보다 더 높은 계층에서는, 라우터라는 특별한 컴퓨터가 여러 개의 비호환 LAN들을 연결시켜서 internet (interconnected network)을 형성한다. 각 라우터는 각 네트워크 (LAN)에 대한 어댑터 (포트)를 가진다. 라우터는 고속의 point-to-point 전화 연결을 해주는데 이것이 바로 WAN이다. WAN (Wide Area Networks)은 LAN보다 더 넓은 지리적 영역에 퍼져 있기 때문에 붙은 이름이다.
일반적으로 라우터는 임의의 LAN과 WAN들을 연결하여 인터넷을 구축한다.
인터넷의 특징
매우 다르고 비호환적인 기술을 가지는 여러 가지 LAN과 WAN으로 인터넷이 구성될 수 있다는 것은 인터넷이 가진 주요 특징이다.
그런데 비호환 네트워크들을 거치면서 source 호스트가 다른 destination 호스트에게 데이터 비트를 전송하는 일은 어떻게 가능한 걸까? 이는 서로 다른 네트워크 사이의 격차를 없애주는 프로토콜 스프트웨어 계층 덕분에 가능한 일이다. 호스트와 라우터에 있는 소프트웨어는 호스트와 라우터가 데이터를 전송할 때 지켜야 하는 것들을 정한 프로토콜을 구현한다.
프로토콜은 두 가지 기본 기능을 제공해야 한다.
명명법 Naming scheme
서로 다른 LAN 기술은 호스트에게 주소를 배정할 때 서로 다른, 비호환적인 방법을 이용한다. 인터넷 프로토콜 internet protocol은 호스트 주소를 위한 통일된 형식을 정의함으로써 이러한 격차를 없앤다. 각 호스트들은 자신을 고유하게 식별하는 인터넷 주소를 적어도 하나 배정받게 된다.
전달 기법 Delivery mechanism
서로 다른 네트워킹 기술들은 비트를 인코딩하는 방벙과 비트를 프레임을 패키징할 때 서로 다른, 비호환적인 방법을 이용한다. 인터넷 프로토콜은 데이터 비트를 패킷 packet이라고 불리는 덩어리로 묶는 통일된 방법을 정의함으로써 이러한 차이를 없앤다. 패킷은 헤더 header(패킷 사이즈와 source hosts, destination hosts 등을 포함하고 있다.)와 페이로드 payload(source host가 보낸 데이터 비트)를 포함하고 있다.
위의 인터넷 예시에서 2개의 LAN이 라우터로 연결되어 있다. LAN 1의 host A에서 운영 중인 클라이언트는 LAN 2의 host B에서 운영 중인 서버에게 데이터 바이트의 시퀀스를 전송한다.
여기에는 8가지 기본 단계가 있다.
- 호스트 A에 있는 클라이언트는 시스템 콜을 호출한다.
- 이 시스템 콜은 클라이언트의 가상 주소 공간으로부터 커널 버퍼로 데이터를 복사한다. - 호스트 A에 있는 프로토콜 소프트웨어는 데이터에 인터넷 헤더와 LAN 1 헤더를 덧붙임으로써 LAN 1 프레임을 생성한다.
- 인터넷 헤더는 받는 사람으로 인터넷 호스트 B를 지정한다.
- LAN 1 프레임 헤더는 받는 사람으로 라우터를 지정한다.
- 프로토콜 소프트웨어는 프레임을 (호스트의) LAN 1 어댑터에게 전달한다.
LAN 1 프레임의 페이로드는 인터넷 패킷이고, 이 패킷의 페이로드는 실제 사용자의 데이터이다.
이러한 캡슐화 encapsulation은 인터 네트워킹 internetworking에서 기본적인 통찰 중 하나이다. - (호스트의) LAN 1 어댑터는 네트워크로 프레임을 복사한다.
- 프레임이 라우터에 도달하면 라우터의 LAN 1 어댑터는 전선으로부터 프레임을 읽어들여서 (라우터의) 프로토콜 소프트웨어에게 전달한다.
- 라우터는 인터넷 패킷 헤더로부터 도착 인터넷 주소 정보를 얻어와서 이 정보를 라우팅 테이블 routing table에 있는 인덱스로서 사용하여 패킷을 어디로 보낼지를 결정한다.
- 라우터는 그 다음에 이전 LAN 1 프레임 헤더를 벗겨 내고, 호스트 B를 받는 사람으로 설정한 새로운 LAN 2 프레임 헤더를 앞에 붙인다. 그리고 완성된 프레임을 (라우터의) LAN 2 어댑터에게 전송한다. - 라우터의 LAN 2 어댑터는 프레임을 네트워크로 복사한다.
- 프레임이 호스트 B에 도달하면, 호스트 B의 어댑터는 전선으로부터 프레임을 읽어들여서 프레임을 (호스트의) 프로토콜 소프트웨어에게 전달한다.
- 호스트 B에 있는 프로토콜 소프트웨어는 프레임에서 패킷 헤더와 프레임 헤더를 벗겨 낸다. 프로토콜 소프트웨어는 마침내 서버가 데이터를 읽어들이는 시스템 콜을 호출했을 때, 데이터를 서버의 가상 주소 공간으로 복사할 수 있게 된다.
물론 우리는 여기에서 많은 어려운 이슈들을 얼버무려서 이야기하고 있다. 만약 다른 네트워크들이 서로 다른 최대 프레임 사이즈 maximum frame size를 가지고 있다면 어떻게 해야 할까? 라우터들은 프레임을 어디로 보내야 할지 어떻게 알 수 있을까? 네트워크 토폴로지가 변화했을 때 라우터들은 어떻게 이 변화를 알 수 있을까? 패킷이 손실되면 어떻게 해야 할까? 이런 질문들에 대한 답도 살펴봐야 한다. 하지만 여기서 알고 넘어가야 하는 것은 인터넷에서 캡슐화라는 전략이 사용된다는 것이다.
3. 글로벌 IP Internet
글로벌 IP Internet은 가장 유명하고 성공적인 internet (internetwork: 서로 연결되어 있는 네트워크들의 집합)의 구현물이다. 글로벌 IP 인터넷은 1969년 이래로 여러 형태로 존재해왔다.
인터넷의 내부 구조가 복잡하고 지속적으로 변화하고 있는 반면, 클라이언트-서버 응용 프로그램의 구조는 초기 1980년대 이래로 상당히 변화 없이 유지되었다.
각각의 인터넷 호스트는 TCP/IP 프로토콜 (Transmission Control Protocol/Internet Protocol)을 구현하는 소프트웨어를 운영한다. TCP/IP 프로토콜은 거의 모든 컴퓨터 시스템에서 지원된다. 인터넷 클라이언트와 서버는 소켓 인터페이스 sockets interface 함수와 UNIX I/O 함수를 섞어 사용하여 서로 소통한다. 소켓 함수는 일반적으로 시스템 콜로 구현된다. 이 시스템 콜은 커널로 빠져 들어가서 TCP/IP와 관련된 다양한 커널 모드의 함수들을 호출한다.
IP 프로토콜
IP 프로토콜은 데이터그램 datagram이라고 알려진 패킷을 전송할 때 사용할 수 있는 전달 메커니즘과 기본 명명법 basic naming scheme을 제공한다. IP 메커니즘은 데이터그램이 네트워크에서 손실되거나 복제됐을 때 그 데이터그램을 복구하기 위해 아무런 노력을 하지 않는다는 점에서 신뢰할 수 없는 unreliable 메커니즘이다.
UDP 프로토콜
UDP (Unreliable Datagram Protocol) 프로토콜은 IP를 살짝 확장해서 데이터그램이 호스트에서 호스트보다도, 프로세스에서 프로세스로 이동될 수 있도록 한 것이다.
TCP 프로토콜
TCP는 프로세스 사이에 신뢰할 수 있는 reliable 완전한 duplex (bidirectional 양방향) 연결을 제공하기 위해 IP 위에 구현된 복잡한 프로토콜이다.
개발자의 관점에서 볼 때 인터넷은 다음과 같은 속성을 가진 전세계적 호스트의 집합이다.
- 호스트는 32 비트 IP 주소에 매핑된다.
- IP 주소는 인터넷 도메인 네임이라고 불리는 식별자에 매핑된다.
- 하나의 인터넷 호스트에 있는 프로세스는 다른 인터넷 호스트에 있는 프로세스와 connection을 통해 통신할 수 있다.
IPv6
기존의 인터넷 프로토콜은 32 비트 주소를 가진 Internet Protocol Version 4(IPv4)이다. 1996년에 Internet Engineering Task Force (IETF)는 128 비트 주소를 가지면서 IPv4를 계승할 Internet Protocol Version 6(IPv6)라는 새로운 버전의 IP를 제안했다. 하지만 그로부터 20년이 지난 2015년 인터넷 트래픽의 대부분은 여전히 IPv4 네트워크에 의해 수행되고 있다. 예를 들어, 오직 4%의 사용자만이 IPv6를 사용하여 Google 서비스에 접근한다.
IP 주소는 부호가 없는 32 비트 정수이다.
네트워크 프로그램은 IP 주소 구조체에 IP 주소를 저장한다. 그런데 IP 주소 구조체에 scalar IP 주소를 저장하는 방식은 초기 소켓 인터페이스의 구현물에서 유래된 어색한 방식이다. IP 주소는 scalar 타입으로 정의하는 것이 더 자연스럽다. 하지만 이미 설치된 응용 프로그램의 기반이 너무 거대하기 때문에 이제 와서 바꾸기에는 너무 늦었다.
인터넷 호스트들은 서로 다른 호스트 바이트 순서를 가질 수 있기 때문에, TCP/IP는 모든 정수 데이터에 대해서 network byte order (big-endian byte order)라는 통일된 순서를 사용한다. 예를 들면 패킷 헤더 안에 담겨 IP 주소를 다룰 때 그렇다. IP 주소 구조체에 있는 주소들은 항상 big-endian network byte order로 저장된다. 호스트 바이트 순서가 리틀 엔디안일지라도 그렇다.
유닉스는 네트워크와 호스트 바이트 순서 간에 변환을 하기 위해 다음과 같은 함수를 제공한다.
/* IP address structure */
struct in_addr {
uint32_t s_addr; /* Address in network byte order (big-endian) */
};
#include <arpa/inet.h>
/* Returns: value in network byte order */
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
/* Returns: value in host byte order */
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(unit16_t netshort);
htonl 함수 (host to network long)
부호가 없는 32 비트 정수를 호스트 바이트 순서에서 네트워크 바이트 순서로 변환한다.
ntohl 함수 (network to host long)
부호가 없는 32 비트 정수를 네트워크 바이트 순서에서 호스트 바이트 순서로 변환한다.
htons 함수 (host to network short)
부호가 없는 16 비트 정수를 호스트 바이트 순서에서 네트워크 바이트 순서로 변환한다.
ntohs 함수 (network to host short)
부호가 없는 16 비트 정수를 네트워크 바이트 순서에서 호스트 바이트 순서로 변환한다.
*64 비트 값을 조작하는 함수는 없다.
IP 주소는 일반적으로 dotted-decimal notation이라는 형식으로 표현된다. dotted-decimal notation은 각 바이트가 10진수로 표현되며 이들이 점으로 구분되는 표기법이다.
<예시> 0x8002c2f2의 dotted-decimal 표현: 128.2.194.242
리눅스 시스템에서는 당신의 호스트의 dotted-decimal 주소를 알아내기 위해 HOSTNAME 이라는 명령어를 사용할 수 있다.
애플리케이션 프로그램은 inet_pton과 inet_ntop 함수를 이용하여 IP 주소와 dotted-decimal 문자열을 왔다갔다 변환할 수 있다.
이 함수 이름에서 "n"은 network를 의미하고, "p"는 presentation을 의미한다. 이 함수들은 32비트 IPv4 주소(AF_INET)와 128 비트 IPv6 주소 (AF_INET6) 모두를 다룰 수 있다.
#include <arpa/inet.h>
/* Returns: 1 if OK, 0 if src is invalid dotted decimal, −1 on error */
int inet_pton(AF_INET, const char *src, void *dst);
/* Returns: pointer to a dotted-decimal string if OK, NULL on error */
const char *inet_ntop(AF_INET, const void *src, char *dst, socklen_t size);
inet_pton
inet_pton 함수는 dotted-decimal 문자열(src)를 네트워크 바이트 순서(dst)로 이진 IP 주소로 변환한다.
- 변환 성공했을 때: 1을 반환
- src가 유효한 dotted-decimal 문자열을 가리키지 않을 때: 0을 반환
- 에러가 있을 때: -1을 반환하고 errno를 설정
inet_ntop
inet_ntop 함수는 이진 IP 주소를 네트워크 바이트 순서로 dotted_decimal 표현으로 변환한다.
- 변환 성공했을 때: dotted-decimal 문자열을 가리키는 포인터를 반환.
- 에러가 있을 때: NULL을 반환
<netinet/in.h>에 struct in_addr 구조체가 정의되어 있다.
<arpa/inet.h>에 htonl, ntohl, htons, ntohs 그리고 inet_pton, inet_ntop 함수가 정의되어 있다.
인터넷 클라이언트와 서버는 서로 소통할 때 IP 주소를 사용한다. 하지만, 큰 정수는 사람들이 기억하기 어렵기 때문에 인터넷은 인간 친화적인 도메인 이름 domain name을 별도로 정의한다. 그리고 도메인 이름과 IP 주소를 매핑하는 메커니즘도 정의한다.
도메인 이름
도메인 이름은 점으로 구분된 단어(문자, 숫자, /)의 sequence이다.(<예시> waleshark.ics.cs.cmu.edu.)
도메인 이름은 계층을 이루고 있다. 계층은 트리처럼 표현된다. 서브 트리들은 서브 도메인이라고 불린다.
루트 노드 Unnamed root
계층 구조의 최상단에는 이름이 붙지 않은 루트 노드 Unnamed root가 있다.
첫 번째 레벨 도메인 이름 First-level domain name
다음 레벨은 첫 번째 레벨의 도메인 이름 First-level domain name이다. 이 계층에 있는 도메인 이름들은 비영리기관인 ICANN (Internet Corporation for Assigned NAmes and Numbers)에 의해 정의된다. 잘 알려진 예로 com, edu, gov, net이 있다.
두 번째 레벨 도메인 이름 Second-level domain name
다음 레벨은 두 번째 레벨 도메인 이름 Second-level domain name이다. 예를 들면, cmu.edu와 같은 것들이다. 이 계층에 있는 도메인 이름들은 다양한 인증받은 ICANN의 대행사에 의해 선착순으로 할당된다.
세 번째 레벨 도메인 이름 Third-level domain name
어떤 기관이 두 번째 레벨의 도메인 이름을 받았다면 그 서브 도메인 안에서 다른 어떤 새로운 도메인 이름을 만들든지 모두 무료이다. 예를 들면 cs.cmu.edu와 같은 식이다.
인터넷은 도메인 이름과 IP 주소 사이의 매핑을 정의한다. 1988년까지 이 매핑은 HOSTS.TXT라는 하나의 텍스트 파일에 수동으로 관리되었다. 그때 이후로는 매핑은 분산된 전세계적 데이터 베이스 DNS (domain Name System)에서 관리되어 오고 있다. 개념적으로 DNS 데이터베이스는 수백만의 호스트 항목으로 이루어져 있다. 호스트 항목은 도메인 이름과 IP 주소 사이를 매핑한다.
리눅스의 NSLOOKUP 프로그램으로 도메인 이름에 매핑된 IP 주소를 보여준다.
각각의 인터넷 호스트는 지역적으로 정의된 도메인 이름 localhost를 가지고 있다. 이는 항상 루프백 주소인 127.0.0.1로 매핑되어 있다.
localhost 라는 이름은 같은 머신에서 돌아가고 있는 클라이언트와 서버를 참조할 수 있는 편리한 방법을 제공한다. 이 방법은 특히 디버깅 시에 유용하다.
우리는 우리 로컬 호스트의 진짜 도메인 이름을 알아내기 위해 HOSTNAME을 사용한다.
가장 간단한 경우 하나의 IP 주소에는 하나의 도메인 이름만 매핑된다. 그런데 어떤 경우에는 하나의 IP 주소에 여러 개의 도메인 이름이 매핑되기도 한다. 가장 일반적인 경우는 동일한 IP 주소 집합에 여러 개의 도메인 이름이 매핑되어 있는 경우이다.
인터넷 호스트는 얼마나 많이 존재하는가?
1987년 이래로 Internet Systems Consortium은 일 년에 두 번 Intenet Domain Survey를 수행한다. 이 survey는 도메인 이름을 배정받은 IP 주소의 수를 집계함으로써 인터넷 호스트의 수를 추정한다. 인터넷 호스트가 약 20,000개 있었던 1987년 이래로 호스트의 수는 기하급수적으로 증가하였다. 2015년까지 10억 개가 넘는 인터넷 호스트가 있는 것으로 알려졌다.
인터넷 클라이언트와 서버는 연결을 통해 바이트 스트림을 전송하고 수신함으로써 통신한다.
- 연결은 두 프로세스를 연결한다는 점에서 연결은 point-to-point 연결이다.
- 연결은 데이터가 양방향으로 같은 시간에 흐를 수 있다는 점에서 완전 양방향 full-duplex이다.
- 연결은 소스 프로세스로부터 전송된 바이트 스트림이 마침내 목적지 프로세스에 의해 수신된다는 점에서 신뢰할 수 있다. 몇 가지 예상치 못한 극단적인 재앙적인 실패를 감안하더라도 말이다.
소켓 socket은 연결의 마지막 포인트 end point이다.
각각의 소켓은 대응되는 소켓 주소 socket address를 가진다. socket address는 인터넷 주소와 16 비트 정수 포트(이 소프트웨어 포트들은 네트워크 스위치와 라우터에 있는 하드웨어 포트와 전혀 관계가 없다.)를 가지고 address:port 표기법으로 나타낸다.
단기 포트 ephemeral port
클라이언트 소켓 주소에 있는 포트는 클라이언트가 연결 요청을 할 때 커널에 의해 자동으로 배정된다. 이를 ephmeral port 단기 포트라고 한다.
잘 알려진 포트 well known port
서버 소켓 주소에 있는 포트는 서비스에 영구적으로 연결되는 포트로, 일반적으로 잘 알려진 포트이다. 잘 알려진 포트에 연결된 각 서비스는 대개 잘 알려진 서비스 이름이 있다.
<예시> 웹 서버-80번 포트-http, 이메일 서버-25번 포트-smpt
잘 알려진 이름과 잘 알려진 포트 사이의 매핑은 /etc/services라고 불리는 파일 안에 저장되어 있다.
connection은 양 끝 end point의 소켓 주소로 이루어진 소켓 주소의 쌍 socket pair으로 고유하게 식별된다.
이는 튜플 (cliaddr:cliport, servaddr:servport)로 표현된다.
여기서 cliaddr은 클라이언트의 IP 주소, cliport는 클라이언트의 포트이고, servaddr은 서버의 IP 주소, servport는 서버의 포트이다.
소감
정글에서 CSAPP를 읽으면서 제일 와닿지 않았던 부분이 네트워크 부분이었다. 그런데 지금 다시 읽으니까 전보다 이해되는 게 많은 것 같다. 특히 이제 연결의 end point인 소켓 주소는 호스트 주소와 프로세스 포트 번호로 이루어져 있다는 것이 잘 받아들여진다.
11장 앞부분에서는 이미 시스템에 구현되어 있는 헤더 파일들에 있는 구조체와 함수 선언을 살펴보는 부분이 많은 분량을 차지하고 있다. 기술 문서를 읽는 것처럼 속도가 잘 안 나기는 하지만 이럴 때 아니면 또 언제 헤더 파일들을 살펴볼까 싶어 차근차근 짚고 넘어가고 있다.