1. 데이터 송수신 동작의 개요

DNS 서버에게 요청하여 IP 주소를 얻으면 웹 서버에게 실제 요청을 보내기 위해 OS 에게 네트워크 송신 의뢰를 보낸다. 이는 브라우저 뿐만이 아니라 네트워크가 필요한 모든 애플리케이션이 동일하게 동작한다. 일반적으로 애플리케이션은 네트워크 송신 기능이 없으므로 OS 에게 의뢰하여 이를 수행한다.

여기에서도 DNS 서버에 IP 주소를 조회할 때와 같이 Socket 라이브러리에 들어있는 프로그램 부품을 이용하는데, IP 주소를 조회할 때처럼 프로그램 부품을 하나씩 호출하고 끝나지는 않는다.

3214992B-C4DF-4F5C-8397-C1D69AE065E6.jpeg

클라이언트와 서버가 데이터를 송수신하기 위해서는 파이프와 같은 연결 통로가 필요하다. 파이프는 물리적으로 존재하는 것은 아니지만 서버와 통신하기 위해서 연결하는 동작이 필요하다.

클라이언트와 서버에서는 외부와 통신하기 위한 출입구인 소켓 이 있다. 서버에서 소켓을 먼저 생성하고 클라이언트의 요청을 기다린다. 그러면 서버에게 요청을 보내고 싶은 클라이언트가 내부적으로 소켓을 만들고, 서버의 소켓에 파이프 를 연결한다. 파이프가 연결되면 원하는 데이터를 송수신할 수 있다.

데이터의 송수신이 끝나면 파이프를 분리하여 연결을 종료한다. 연결을 할 때에는 클라이언트가 파이프를 연결하였으나 연결을 종료할 때는 어느 쪽에서 분리해도 상관없다. 파이프가 분리되면 소켓이 제거되며 통신이 종료된다.

  1. 소켓을 생성한다. (소켓 작성 단계)
  2. 서버 측의 소켓에 파이프를 연결한다. (접속 단계)
  3. 데이터를 송수신한다. (송수신 단계)
  4. 파이프를 분리하고 소켓을 제거한다. (연결 끊기 단계)

위의 단계는 애플리케이션이 OS 내부의 프로토콜 스택에게 의뢰한 과정을 정리한 것이다.

2. 소켓의 작성 단계

DNS 서버에 IP 주소를 요청했을 때처럼 Socket 라이브러리의 메서드를 실행한다. 도메인 주소로 IP 주소를 찾을 때에는 gethostbyname() 을 호출했고, 소켓을 생성할 때에는 socket() 을 호출한다. socket() 을 호출하면 소켓을 식별할 수 있는 디스크립터를 반환받는다.

참고로 하나의 컴퓨터에서 여러 대의 서버에 접속하여 데이터를 받는 경우가 많다. 이는 하나의 컴퓨터에서 여러 개의 소켓을 생성할 수 있다는 것을 의미한다. 예를 들어 브라우저의 창을 여러개 띄워놓는 경우가 있다.

3. 파이프를 연결하는 접속 단계

클라이언트 측에서 만든 소켓을 서버의 소켓으로 연결하기 위해 connect() 를 호출한다. connect() 를 호출할 때는 소켓의 디스크립터, 서버의 IP 주소, 포트 번호가 필요하다.

디스크립터는 클라이언트 측에 있는 여러 개의 소켓 중 어느 소켓을 사용할 것인지 결정하기 위해 필요하다. IP 주소는 DNS 서버에 요청해서 받은 IP 주소로, 어느 PC 에 접근할 것인지 알기 위해 필요하다. 특정한 PC 에 접속한 후에는 서버의 어느 애플리케이션의 소켓과 연결할 것인지 알기 위해 포트 번호가 필요하다.

4. 메시지를 주고받는 송수신 단계

connect() 를 통해 파이프가 연결되면 이제 데이터를 주고 받을 수 있는 상태가 된다. 어느 쪽에서든 소켓에서 데이터를 쏟아 부으면 상대측의 소켓에 데이터가 도착한다.