n 네트워크 계층이 제공하는 호스트 - 호스트에서 애플리케이션에 대한 프로세스 - 프로세스 전달 서비스로 확장하는 것을 이 장에서 살펴본다.

목적지 호스트에서 트랜스포트 계층은 바로 아래 네트워크 계층으로부터 세그먼트를 수신한다. 트랜스포트 계층은 호스트에서 동작하는 해당 애플리케이션 프로세스에 이 세그먼트 데이터를 전달하는 의무를 가진다.

네트워크 애플리케이션의 한 부분으로서 프로세스가 소켓(socket) 을 가지고 있다. 이를 통해 네트워크에서 프로세스로 데이터를 전달하고, 반대로 전달하는 출입구 역할을 한다. 그러므로 수신 측 호스트의 트랜스포트 계층은 실제로 데이터를 직접 프로세스로 전달하지 않는다. 대신 중간 매개자인 소켓에게 전달한다. 주어진 시간에 수신 측 호스트에 하나 이상의 소켓이 있을 수 있으므로, 각각의 소켓은 하나의 유일한 식별자를 갖는다. 이 식별자의 포맷은 소켓이 UDP 소켓인지 TCP 소켓인지에 따라 달라진다.

이제 수신 측 호스트가 수신한 트랜스포트 계층 세그먼트를 어떻게 적절한 소켓으로 향하게 하는지 알아보자. 각각의 세그먼트는 이런 목적을 위해 세그먼트에 필드 집합을 가지고있다. 수신 측의 트랜스포트 계층은 수신 소켓을 식별하기 위해 이런 필드를 검사한다. 그리고 해당하는 세그먼트를 해당 소켓에 보낸다. 세그먼트의 데이터를 올바른 소켓으로 전달하는 작업을 **역다중화(demultiplexing)**라 한다. 출발지 호스트에서 소켓으로부터 데이터를 모으고, 이에 대한 세그먼트를 생성하기 위해 각 데이터에 헤더 정보(나중에 역다중화에 쓰임)로 캡슐화 하고, 그 세그먼트들을 네트워크 계층으로 전달하는 작업을 **다중화(multiplexing)**이라 한다.

그림에서 중간 호스트의 트랜스포트 계층은 네트워크 계층으로 부터 수신한 세그먼트를 위쪽의 프로세스 P1 or P2로 반드시 역다중화 해야한다. 또한 중간 호스트의 트랜스포트 계층은 프로세스의 소켓으로부터 외부로 나가는 데이터를 모으고, 다음엔 트랜스포트 계층 세그먼트들로 만들고, 이 세그먼트들을 아래 네트워크 계층으로 전달해야 한다. 비록 인터넷 트랜스포트 프로토콜의 내용에서 다중화와 역다중화를 설명했지만, 이들은 한 계층에서의 한 프로토콜이 그 상위 계층의 여러 프로토콜로 의해 사용될 때마다 관련되는 것임을 알아두길 바란다.

멀티 플렉싱이 모으는거로 디멀티플렉싱이 분배라 생각하면 될까?

멀티플렉싱 vs 디멀티플렉싱

  • 멀티플렉싱 (Multiplexing) = “모으기”

    • 여러 개의 데이터 스트림을 하나의 채널로 합치는 과정
    • 송신 측에서 수행
  • 디멀티플렉싱 (Demultiplexing) = “분배하기”

    • 하나의 채널로 온 데이터를 여러 개로 나누어 배분하는 과정
    • 수신 측에서 수행

이제 트랜스포트 계층의 다중화, 역다중화를 알아봤으니, 이걸로 실제로 호스트에서 어떻게 수행되는지 살펴보자. 앞서 내용에서, 다중화에는 다음 두 가지 요구사항이 있음을 알 수 있다. 첫째, 소켓은 유일한 식별자를 갖는다. 둘째, 가 세그먼트는 세그먼트가 전달될 적절한 소켓을 가리키는 특별한 필드를 갖는다. 이 특별한 필드는 출발지 포트 번호 필드(source port number field)와 복적지 포트 번호 필드(destination port number field)다. 각각의 포트는 0 ~ 65535까지의 16비트 정수다. 그중 0 ~ 1023까지의 포트 번호를 잘 알려진 포트(well known port number)로 하여 사용을 엄격히 금한다.

호스트의 각 소켓은 포트 번호를 할당받는다. 그리고 세그먼트가 호스트에 도착하면, 트랜스포트 계층은 세그먼트 안의 목적지 포트 번호를 보고 상응하는 소켓으로 세그먼트를 보낸다. 앞으로 살펴보겠지만 이건 UDP의 기본적인 동작방식이다. TCP의 다중화/역다중화는 좀 더 많은 의미를 갖고 있음을 이후에 공부할 것

비연결형 다중화와 역다중화

2.7.1 절에서 호스트에서 수행되는 파이썬 프로그램은 한 줄의 명령으로 UDP 소켓을 생성할 수 있었다.

clientSocket = socket(A_INET, SOCK_DGRAM)

이 방법으로 UDP 소켓이 생성 될 때, 트랜스포트 계층은 소켓에게 자동으로 포트번호를 할당한다. 다른 방법으로는 소켓을 생성한 뒤 소켓 bind() 방식을 사용하여 특정 포트 번호(여기선 19157)를 UDP 소켓에 할당하기 위해 코드 한 줄을 추가할 수 있다.

clientSocket.bind(('', 19157))

목적지 IP 주소와 목적지 포트 번호가 같으면 동일한 호스트를 향한다. 출발지 포트번호는 ‘회신 주소’의 한 부분. 보낸이와 받는이를 거꾸로하면 보낸사람한테 받은 사람이 메시지를 보낼수 있지 않은가? 그 원리임

연결지향형 다중화와 역다중화

TCP 역다중화를 하려면 TCP 소켓과 TCP 연결 설정을 살펴봐야한다. TCP 소켓과 UDP 소켓의 다른 점은 TCP 소켓은 4개의 요소 집합, 즉 출발지 IP 주소, 출발지 포트 번호, 목적지 IP 주소, 목적지 포트 번호 에 의해 식별된다는 것. 그래서 호스트에 TCP 세그먼트오면, 호스트는 해당되는 소켓으로 세그먼트를 전달(역다중화)하기 위해 4개의 값을 모두 사용한다. 특히, UDP와는 다르게 다른 출발지 주소 또는 다른 출발지 포트 번호를 가지고 도착하는 2개의 TCP 세그먼트(초기 연결 설정 요청하는 TCP는 제외) 2개의 다른 소켓으로 향하게 된다.

  • TCP 서버 애플리케이션은 ‘환영 소켓’을 갖고 있다. 이 소켓은 포트 번호 12000을 가진 TCP 클라이언트로부터 연결 설정 요청을 기다린다.
  • TCP 클라이언트는 다음과 같은 명령으로 소켓을 생성하고 연결 설정 요청 세그먼트를 보낸다.
clientSocket = socket (AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, 12000))
  • 연결 설정 요청은 목적지 포트 번호 12000과 TCP헤더에 설정된 특별한 연결 설정 비트를 가진 TCP 세그먼트일 뿐이다. 또한 그 세그먼트는 출발지 포트 번호를 포함하는데, 이건 클라이언트가 선택한 번호.
  • 서버 프로세스로 동작하는 컴퓨터의 호스트 운영체제가 목적지 12000을 포함하는 연결 요청 세그먼트를 수신하면, 이 세그먼트를 포트 번호 12000으로 연결 수락을 기다리는 서버 프로세스로 보낸댜.

connectionSocket, addr = serverSocket.accept()

  • 또한 서버는 연결 요청 세그먼트를 다음과 같은 4 가지 값을 주목한다.
  1. 세그먼트 안의 출발지 포트 번호
  2. 출발지 호스트의 IP 주소
  3. 세그먼트 안의 목적지 포트 번호
  4. 목적지 IP 주소 새롭게 생성된 연결 소켓은 이 4가지 값에 의해 식별된다.

서버 호스트는 동시에 존재하는 많은 TCP 소켓을 지원할 수 있다. 이 각각의 소켓은 프로세스에 접속되어 있으머, 이들 소켓은 4개의 요소의 집합에 의해 식별된다. TCP 세그먼트가 호스트에 도착하면 4가지 필드(출발지 IP, 목적지 IP, 출발지 포트, 목적지 포트)모두는 해당해되 소켓으로 세그먼트를 전달(역다중화) 위해 사용된다.

다음 그림에서 호스트 C가 서버 B로 2개의 HTTP 세션을 시작하고, 호스트 A가 호스트 B로 하나의 HTTP 세션을 시작하는 상황이 설명되어있다.

웹 서버와 TCP

14페이지!!!