reference: "모두를 위한 리눅스 프로그래밍" / 아오키 미네로
"TCP/IP Sockets in C 2/e" / 마이클 도나후, 케네스 칼버트
하나의 머신 안에서든, 네트워크를 넘어서든, 다루는 것은 결국 스트림일 뿐이다. 스트림이라면 read()나 write()를 통해 데이터를 읽고 쓸 수 있으므로 결국 어떻게 스트림을 얻느냐의 차이만 있을 뿐이다.
이전에는 주로 open() 시스템 콜을 사용하여 스트림을 얻었다. 파일의 경우에는 파일의 이름(경로)를 지정하여 연결된 스트림을 만들어 달라고 커널에 의뢰했다. 네트워크 통신도 동일하다. 먼저, 네트워크에 연결된 컴퓨터에는 통신을 받아들이는 프로세스가 존재한다. 이것이 파일에 대응하는 존재이다. 또한 네트워크 너머의 컴퓨터는 이름을 가진다. 그래서 커널에 그 이름을 전달하여 스트림을 얻게 된다.
네트워크에 관해 언급할 때는 컴퓨터란 용어 대신 호스트(host)나 노드(node)란 표현을 주로 사용한다.
아래 그림은 호스트와 라우터에서의 프로토콜, 응용 프로그램, 소켓 API 간의 관계 및 TCP를 이용하는 하나의 응용 프로그램에서 다른 응용 프로그램으로의 데이터 흐름을 나타낸다.

TCP와 IP의 이름이 붙은 네모 상자는 각 프로토콜이 구현된 것을 나타내며, TCP/IP의 구현은 보통 호스트 상 운영체제 내부에 존재한다. 응용 프로그램은 그림의 점선에서 표현된 소켓 API를 통해 TCP 또는 UDP의 서비스에 접근하게 된다.
TCP/IP에서 하부 계층은 이더넷이나 전화 모뎀 연결과 같은 하부 통신 채널로 이루어져 있다. 이러한 하부 채널들은 라우터가 하는 것처럼 패킷을 목적지로 전달하는 기능을 담당하는 네트워크 계층에 의해서 사용된다.
TCP/IP 프로토콜 군에서 네트워크 계층을 구성하는 프로토콜은 인터넷 프로토콜(IP)뿐이다. IP는 임의의 두 개의 호스트 사이에 존재하는 여러 개의 채널과 라우터의 순서를 마치 "하나의 호스트-호스트 연결" 채널처럼 보이게 만든다.
IP는 데이터그램 서비스를 제공한다. 편지와 소포가 우편 시스템에 보내지는 것과 같이 IP 레벨에서는 스트림이란 개념보다는 패킷이란 개념만 존재한다. 패킷이란 데이터의 뭉치(즉, 바이트 열)를 말한다.
IP에서 재밌는 것은 많은 호스트가 패킷을 계주 릴레이처럼 전송하고 있는 부분이다. 패킷을 받은 호스트는 자신에게 온 패킷이라면 받아들이고, 그것이 아니라면 다른 곳으로 보낸다. 따라서 패킷은 순서대로 도착하지도 않고, 잘 전송되었다고 보장하기도 어렵다.
IP는 단순히 최선 전달 서비스(best-effort service)만을 할 뿐이다. IP는 일부로 전송을 게을리 하지 않으면서 최선을 다한다. 다만 전송 시 생기는 문제는 있을 수 있으며 이를 극복하거나 보장하는 시스템을 갖추고 있지 않고 ICMP(인터넷 제어 메시지 프로토콜)를 통해 알리는 시스템이 있을 뿐이다.
IP 계층 위에 존재하는 계층을 전송 계층(transport layer)이라 한다. 해당 계층은 TCP와 UDP, 2개의 선택 프로토콜을 제공한다. 이 2개의 프로토콜 서비스를 이용해 각각 다른 전송 기능을 제공하며, 응용 프로토콜(application 계층의 프로토콜)의 전송 특징에 따른 필요성에 의해 그에 맞는 프로토콜이 선택적으로 사용된다.
마치 IP 프로토콜은 어떤 호스트에서 다른 호스트로 데이터를 전달하는 것을 담당하고, TCP/UDP 프로토콜은 어떤 프로그램에서 다른 프로그램으로 데이터를 전달하는 것을 담당하는 것과 같다.
TCP와 UDP를 종단 간 전송 프로토콜(end-to-end protocol)이라고 부른다.
IP가 패킷의 세계라고 한다면, 우리가 얻고 싶은 스트림은 어디서 나오는 것일까? 바로 IP 위 상위 프로토콜이 얹혀서 스트림이 보이게 된다. 이를 위한 프로토콜을 TCP라고 한다.
스트림은 바이트의 열이다. 이 바이트의 열을 앞에서부터 일정 크기로 자르고, 각 부분에 번호를 붙여서 패킷으로써 전송한다. 받는 쪽에서는 패킷 번호를 보고 데이터를 재형성한다. 그리고 빠진 부분 없이 바이트 열이 만들어지면 스트림으로 다룰 수 있게 된다.
=> TCP 프로토콜에 의해 프로세스는 "스트림"으로만 보고 다루면 된다.
TCP는 IP가 제공하는 호스트-호스트 전달 과정(최선 전달)에서 일어날 수 있는 손실/복제/기타 오류 등의 검출과 복구 기능을 수행하도록 설계되어있다.
신뢰성 있는 바이트-스트림 채널을 제공하여 연결 지향적 프로토콜이라 불린다(통신 전에 두 개의 프로그램은 반드시 TCP 연결을 설정해야 함).
TCP 연결
TCP 연결이란 두 개의 통신 컴퓨터에 구현된 TCP 계층 사이에서 "핸드셰이크 메시지"를 교환하면서 이루어진다.
이처럼 TCP는 IP의 패킷 통신 위에 스트림을 만들어내는 프로토콜인데, 패킷의 특성을 그대로 사용한 UDP라는 프로토콜도 있다. UDP는 패킷이 도착하는 순서가 보장되지 않고, 패킷을 잃어버릴 가능성도 있다. 그 대신 TCP에 비해 속도가 빠르고 처리도 간단하다는 특징을 지녔다.
UDP는 IP가 가지는 오류를 복구하려 하지 않고, 단순히 IP의 최선 전달 서비스를 확장하여 호스트 간의 전달이 아닌 두 개의 응용 프로그램 간의 전달이 가능하도록 한다.
UDP를 이용하는 응용 프로그램은 데이터 손실, 순서 바뀜 등의 오류에 대비해야 한다.
TCP와 UDP 프로토콜의 공통 기능은 세분화된 주소 지정(addressing) 기능이다. 어떠한 패킷이 자신이 원하는 응용 프로그램에 도착하기 위해서는 IP와 다른 좀 더 세분화된 주소 지정이 필요하다. TCP와 UDP는 호스트 내 응용 프로그램들을 구분하기 위해 포트 번호라는 주소를 사용한다.
각 IP 주소는 하나의 호스트와 해당 호스트 하부에 존재하는 통신 채널, 즉 네트워크 인터페이스(network interface) 사이에 존재하는 네트워크 연결을 의미한다.
하나의 호스트는 여러 개의 인터페이스를 가질 수 있다. 예를 들어 유선랜(이더넷) 연결과 무선랜(와이파이) 연결 모두를 가지는 호스트를 생각해 볼 수 있다. 하나의 호스트에 여러 개의 네트워크 연결이 있을 수 있다.
하나의 호스트는 다수의 인터페이스를 가질 수 있고, 하나의 인터페이스도 IPv4와 IPv6 주소 등 여러 개의 주소를 동시에 가질 수 있다
인터넷에서 파일 시스템의 파일 이름에 대응하는 것이 IP 주소나 포트 번호이다. 인터넷에 연결된 호스트(컴퓨터)는 반드시 하나 이상의 IP 주소를 가지고 있어 이것으로 해당 호스트를 특정지을 수 있다.
포트 번호는 16비트 부호 없는 숫자(0~65,535)이다. 하나의 호스트가 하나의 기차역이라고 생각한다면, 포트 번호는 역의 선로에 해당한다. 하나의 역에서 여러 대의 열차가 오고 갈 수 있듯이 하나의 IP 주소에도 여러 회선이 연결될 수 있다.
선로에서 열차가 오는 것을 기다리고 있는 것이 앞서 말한 대로 해당 호스트에서 돌아가고 있는 특정 프로세스이다. 이렇게 접속을 기다리면서 어떤 작업을 해주는 프로세스를 서버 프로세스라고 한다. 한편, 서버에 접속해서 어떤 작업을 수행하는 프로세스를 클라이언트 프로세스라고 한다.

well-known port
어떤 서버가 어떤 포트로 대기 중인 정보는 어떻게 알 수 있나?
이것은 사전에 공유되지 않는 한 알 수 없다. 다만, 유명한 서비스들은 정해진 포트를 사용하곤 한다. 예를 들어 메일을 송신할 때 사용하는 SMTP(Simple Main Transfer Protocol)는 25번 포트, 웹 브라우저가 사용하는 HTTP(Hyper Text Transfer Protocol)은 80번 포트를 사용한다. 이것들을 알려진 포트라고 한다.
특별한 용도로 사용하기 위해 예약된 주소 그룹
1. 루프백 주소(loopback address)
IPv4: 127.0.0.1
IPv6: 0:0:0:0:0:0:0:1
이 주소는 항상 루프백 인터페이스라고 하는 가상의 디바이스에 할당되어 있으며, 이 가상의 인터페이스는 전송한 패킷을 즉시 전송자에게 돌려보내는 기능을 가지고 있다. 따라서 테스트 시에 매우 유용하다. 게다가 모든 호스트가 이런 루프백 주소를 가지고 있으며, 심지어 실제 네트워크 인터페이스가 없어도 사용이 가능하다.
2. 사설 용도 할당 주소
IPv4: 10 또는 192.168로 시작하는 주소 또는 172로 시작하고 두 번째 번호가 16~31의 값을 가지는 주소
(IPv6는 사설 주소 없음)
사설 용도 할당 주소는 원래 인터넷이 아닌 사설 네트워크에서 사용되도록 설계되었지만 현재는 네트워크 주소 변환(NAT) 기법을 사용한 주소 변환기를 이용하여 가정이나 회사에서의 인터넷 연결에 사용되기도 한다. NAT 변환기는 자신이 가지고 있는 인터페이스의 사설 주소-포트 쌍에 해당하는 값을 외부로 나가는 인터페이스 공인 주소-포트 쌍에 매핑하는 역할을 한다. 이를 통해 가정이나 회사와 같은 환경에 있는 여러 대의 호스트가 효율적으로 공인 IP 주소를 공유하는 것이 가능해 진다.
3. 링크 지역 주소(또는 자동 설정 주소)
IPv4: 169.254로 시작
IPv6: 처음 16비트 부분이 FE80, FE90, FEA0, FEB0으로 시작
이 주소는 흔히 랜(LAN)이라고 하는 동일한 네트워크에 존재하는 호스트 사이의 통신에만 사용이 된다. 패킷의 목적지가 이와 같은 링크 지역 주소를 포함하고 있다면 라우터는 해당 패킷을 전달하지 않게 된다.
4. 멀티캐스트 주소
IPv4: 224~239로 시작
IPv6: FF로 시작
보통의 IP 주소(유니케스트)가 하나의 목적지를 가리키는 반면 멀티캐스트 주소는 잠재적으로 임의의 목적지들을 가리킨다.