WIL: WEEK 7

서인·2023년 5월 22일
0

WEEK 7, tiny 서버 구현을 위한 관련 이론들을 모두 이해하고 나서 정리한 자료이다.

클라이언트 서버 모델

모든 네트워크 응용 프로그램은 클라이언트 서버 모델에 기초한다. 이 모델은 하나 이상의 클라이언트와 하나의 서버로 나뉘는데, 클라이언트가 서버에게 서비스를 요청하고, 서버는 요청을 받고 리소스를 조작한 뒤(파일을 관리하고 읽고 실행하는 등의 작업), 응답을 클라이언트로 보내는 식으로 구성되며 이 동작을 트랜잭션(transaction)이라고 한다.

한 가지 포인트는 클라이언트와 서버는 프로세스이지 네트워크에 연결된 컴퓨터가 아니라는 점이다. 하나의 호스트에서 여러 개의 클라이언트와 서버를 동시에 실행할 수 있으며, 클라이언트와 서버 트랜잭션은 같거나 다른 호스트에 존재할 수 있다.

네트워크

호스트에게 있어서 네트워크는 그저 입출력 시스템이며, 입출력 버스의 확장 슬롯에 꽃혀있는 어댑터는 네트워크에 물리적인 인터페이스를 제공한다. 네트워크를 수신한 데이터는 입출력 버스를 거쳐서 어댑터에서 메모리로, DMA(Direct Memory Access, 직접 메모리 접근) 전송으로 복사된다.

네트워크 범위

LAN(Local Area Network) - 근거리 통신망을 뜻한다. 건물 안과 같이 제한된 지역에서 통신할 때 쓰이며 근거리 통신이기 때문에 빠르고 오류가 비교적 적다.

WAN(Wide Area Network) - 랜과 랜이 연결되는 광역 통신망을 뜻한다. 랜보다 지리적으로 더 넓은 지역에서 사용하며 원거리 통신이라 랜보다는 느리고 오류가 많다.

Ethernet(이더넷)

LAN은 대부분 이더넷을 사용해 통신한다. 몇 개의 전선들과 허브라고 부르는 작은 상자로 구성된 것을 이더넷 세그먼트라고 하는데, 대개 방이나 빌딩의 층과 같이 작은 지역에 설치한다. 이더넷의 한쪽 끝은 호스트의 어댑터에 연결되고, 다른 쪽은 허브의 포트에 연결된다. 허브는 각 포트에서 수신한 모든 비트를 다른 모든 포트로 복사한다. 그럼에도 불구하고 다른 포트가 아닌 목적지 호스트까지 올바르게 데이터를 전송할 수 있는 이유가 뭘까?

이더넷 어댑터는 MAC이라는 고유한 48비트 주소를 가진다. 앞쪽 24비트는 랜 카드 제조사 번호, 나머지 24비트는 제조사가 붙인 일련번호이다. 호스트는 프레임이라고 부르는 비트들을 다른 호스트로 보낼 수 있다. 각 프레임은 프레임의 소스와 목적지, 프레임의 길이 식별이 가능한 헤더 비트를 가지고 있으며 그 뒤로는 데이터 비트가 이어진다. 아래 그림은 이더넷 프레임의 구조이다.

헤더에는 출발지와 목적지 주소가 담겨있기 때문에 허브에서 모든 포트를 통해 데이터를 전송해도 호스트는 자신의 주소와 목적지 주소가 일치할 때에만 데이터를 읽는다.

전선과 브릿지라고 하는 작은 상자들을 사용해서 여러 개의 이더넷 세그먼트가 연결된 브릿지형 이더넷이라고 하는 더 큰 LAN을 구성할 수 있다. 브릿지형 이더넷은 전체 빌딩이나 캠퍼스 규모로 설치할 수 있으며, 브릿지-브릿지, 브릿지-허브로 연결된 구조를 가지고 있다.

브릿지는 허브처럼 데이터를 모든 포트로 보내는 것이 아니고 분산 알고리즘을 사용해서 어떤 호스트가 어떤 포트로 도달 가능한지 학습하고, 필요한 경우에만 하나의 포트에서 다른 포트로 프레임을 복사한다.

이처럼 네트워크는 다른 기술을 갖는 여러가지의 LAN과 WAN으로 이루어져있다. 그렇다면 어떻게 호스트가 다른 기술을 가지고 있는 네트워크들을 거쳐서 목적지로 데이터를 전송할 수 있을까?

프로토콜(Protocol)

각 호스트와 라우터에서 돌고있는 프로토콜은 서로 다른 네트워크 간의 차이를 줄여주고 서로 통신할 수 있게 해주는 역할을 한다. 프로토콜이란 서로 다른 컴퓨터로 데이터를 전송하기 위해 만들어진 규약이다. 이 프로토콜은 두 가지 기본 기능을 제공한다.

Naming Scheme(명명법): 호스트에는 최소 한 개의 IP(internet protocol) 주소를 할당한다.

Delivery Mechanism(전달기법): 데이터를 패킷으로 묶을 때 같은 방식을 사용한다. 패킷이란 이더넷 프레임과 유사한 형태인데, 데이터 앞에 IP 헤더가 붙은 형태를 말한다.

패킷과 이더넷 프레임의 차이점은 패킷은 3계층에서 network layer 단위로 네트워크를 통해 전송될 때 L3 스위치, 라우터 등에서 전달하는 전송단위이고 이더넷 프레임은 2계층에서 전송되는 단위로 오류 확인을 위한 checksum, 송수신 호스트의 주소 등이 포함된다.

데이터를 전송하는 쪽에서 IP 헤더와 이더넷 프레임 헤더를 추가해 프레임을 생성하는 과정을 encapsulation(캡슐화)이라고 한다. 데이터를 받는 쪽에서 헤더를 추가해 프레임을 생성하면 역캡슐화라고 부른다. 이러한 과정은 네트워크의 근본적인 개념 중 하나이다.

위 그림은 인터넷 프로토콜의 예제다. 하나의 라우터에 연결된 2개의 랜으로 구성되어 있으며, 인터넷에서 호스트에서 다른 호스트로 데이터를 전달하는 과정을 보여준다.

  1. 호스트 A의 클라이언트는 클라이언트 가상 주소공간에서 커널 버퍼로 데이터를 복사하는 시스템 콜을 호출한다.

  2. 프로토콜 소프트웨어는 인터넷 헤더와 LAN1 프레임 헤더를 추가해서 LAN1 프레임을 생성한다. 인터넷 헤더 >> 인터넷 호스트 B로 주소가 지정되고 LAN1 프레임 헤더는 라우터로 주소가 지정된다. 그리고 이 프레임을 어댑터로 전달한다.

  3. 어댑터가 프레임을 네트워크로 복사한다.

  4. 프레임이 라우터에 도달했을 때, 라우터의 LAN1 어댑터가 프레임을 읽어서 프로토콜 소프트웨어로 전달한다.

  5. 라우터가 LAN1 프레임헤더를 제거하고 LAN2 프레임 헤더를 앞에 붙여서 어댑터로 전달한다. 인터넷 주소를 가져와서 패킷을 전달하기 위함이다.

  6. LAN2 어댑터는 프레임을 네트워크로 복사한다.

  7. 프레임이 호스트 B에 도착하면 어댑터가 읽어들인 후 프로토콜 소프트웨어로 전달한다.

  8. 프로토콜 소프트웨어가 패킷 헤더와 프레임 헤더를 벗겨낸다. 서버가 이 데이터를 읽는 시스템 콜을 호출할 때 해당 데이터를 서버의 가상 주소공간으로 복사한다.

TCP/UDP

IP는 기본 명명법과 전달기법을 통해 한 인터넷 호스트에서 다른 호스트로 보낼 수 있는 배달 메커니즘을 제공한다. 하지만 IP가 가지고 있는 문제점들이 있는데, 크게 두 가지다.

비연결성 - IP 메커니즘은 만약 패킷을 받을 대상이 없거나 서비스 불능 상태여도 데이터를 전달한다. IP는 헤더가 깨지지 않았는지 확인하거나 수신자의 주소가 존재하는지에 관한 체크는 진행하나, 수신자가 현재 데이터를 받을 수 있는 상태인지 아닌지에 대해서는 확인하지 않는다.

비신뢰성 - 중간에 패킷을 잃어버리거나 네트워크 상에서 문제가 발생할 때 복구하지 않는다. IP packet은 총 64KB까지 전송이 가능하다. 이를 상회하는 데이터를 보낼 경우 여러 개의 패킷으로 쪼개져서 전송되는데, 하나라도 누락되면 전체가 다 누락된다.

Congestion, 즉 네트워크 경로 상의 장비나 회선의 과부하가 생겨 traffic을 드랍하는 문제가 생겨도 IP는 최선을 다해 전송을 시도할 뿐 전송을 보장하지는 않기 때문에 복구하지 않는다. IP 헤더에는 전송을 보장하는 field가 없기 때문이다. 이를 best-effort라고 한다.

TCP(Transmission Control Protocol)

TCP는 연결 지향 방식이다. 이 말은 세그먼트(segment)를 전송하기 위한 경로를 배정한다는 뜻인데, 3-way handshaking이라는 방식을 사용해 연결을 설정하고 4-way handshaking을 통해 연결을 해제한다. TCP는 하나씩 끊겨서 전송되지만 데이터가 연속으로 흐르는 것 같은(stream) 환경을 제공할 수 있고, 속도는 느리지만 신뢰성이 높으며 안정적인 통신이다.

TCP가 보내는 각 패킷에는 sequence number가 할당되는데, 데이터 전송의 순서와 정확성을 보장하기 위해 사용된다. Sequence number는 총 4가지의 메인 기능이 있다.

  • 데이터 순서 보장: 데이터 전송 순서를 지정하기 때문에, seq num을 사용하여 패킷을 정확한 순서롤 재조립할 수 있다.

  • 중복 패킷 감지: 동일한 seq num이 수신된다면 중복으로 간주하고 폐기한다.

  • 분실된 패킷 복구: Seq num을 기반으로 전송되지 않은 패킷을 확인하고, 만약 손실되었다면 패킷의 재전송을 요청한다.

  • 흐름 제어: Seq num을 통해서 송신자에게 원하는 만큼의 데이터를 수신하거나 중지할 수 있다.

Acknowledgement number는 수신한 데이터의 확인 응답을 보내기 위해 사용되는 값이다. ACK num으로 다음과 같은 기능을 수행할 수 있다.

  • 데이터 수신 확인: 수신자가 데이터를 정상적으로 수신했음을 알리기 위해 ACK num에 수신한 패킷들 중 가장 높은 seq num을 담아서 보낸다. 이는 수신자가 해당 seq num 이전의 데이터는 모두 수신했으며, 만약 다음 데이터를 받게 된다면 해당 seq num보다 커야한다는 정보를 제공한다.

  • 재전송 요청: 수신자는 예상되는 다음 seq num보다 작은 ack 번호를 포함한 ack 패킷을 보내면서 손실된 패킷의 재전송을 요청한다.

  • 흐름 제어: ACK 번호를 증가시킴으로써 송신자에게 데이터의 수신 가능 여부를 전달한다.

Window size는 수신자의 여력을 확인한다. 수신자가 수용할 수 있는 데이터를 확인하고 보내려는 데이터가 수용 가능한 사이즈보다 더 크다면 사이즈를 줄인다. 송신자는 해당 사이즈만큼만 데이터 전송이 가능하다.

3-way handshaking이란 데이터 전송 전에 세그먼트를 3번 교환하여 연결을 확립하는 것을 뜻한다.

  1. 송신자가 sequence number를 생성해서 SYN(synchronize) 패킷에 담아 보낸다(SYN의 값은 랜덤하게 정해진다).

  2. 수신자도 seq num을 생성해서 SYN에 담아 보낸 뒤 수신자에게 받은 seq num에 +1을 해서 ACK로 보낸다.

  3. 송신자도 받은 seq num에 +1해서 ACK로 보낸다.

위 그림을 보면 주고받는 syn과 ack가 1씩 증가하는 것을 알 수 있다.

연결 종료는 4-way handshaking을 통해 하는데, 서로 연결 종료를 요청하고 응답하는 방식으로 세그먼트를 교환한다.

또한 TCP는 보내려는 데이터가 64KB 이상이라면 전송하는 데이터 양에 따라 IP packet 여러 개로 쪼개서 전송하는데, 이는 IP 프로토콜에서 주관한다.

UDP(User Datagram Protocol)

UDP는 비연결형 프로토콜이다. 포트를 제공하고 checksum을 계산하는 것 이외에는 특별한 기능이 없는데, 이는 네트워크 계층 IP의 기능을 전송계층에서 쓰게하기 위해 만들어진 프로토콜이기 때문이다.

UDP는 IP의 속성을 가지고 있어서 64KB까지 전송이 가능하며 best-effort 형식으로, 전송을 보장하지 않는다(비신뢰성). 또한 데이터를 쪼개고 재결합하는 기능도 제공하지 않는다. 혼잡 제어나 패킷의 순서를 부여하는 등의 작업을 하지 않기 때문에 TCP보다는 빠르다. 아래 그림은 TCP와 UDP의 차이점을 좀 더 보기 쉽게 나타내준다.

++ 여기서 추가로 알아두어야 할 부분은, network layer(네트워크 계층)에서는 패킷이라는 전송 단위를 쓰지만 transport layer(전송계층)의 단위를 정의할 때는 TCP를 segment, IP와 UDP는 datagram이라고 부른다. segment와 datagram은 패킷이랑 뜻은 같으나 패킷은 네트워크 계층에서만 사용하며 IP 프로토콜을 기반으로 동작하며 구조 또한 다르다. 그러므로 UDP packet, TCP packet이라는 표현은 사실상 부적합하다.

(그렇다면 IP packet과 IP datagram은 무슨 차이일까도 궁금해서 알아봤으나 사전적 의미는 동일하다고 한다.)

DNS(Domain Name System)

인터넷 클라이언트와 서버는 서로 통신할 때 IP 주소를 사용하지만 사람들이 기억하기는 쉽지 않다. 그렇기 때문에 도메인을 사용해서 기억하기 쉽게
단어의 배열로 만들고, 필요할 때 주어진 이름에서 IP를 찾아서 알려주는 것이 DNS이다. DNS 서버는 서버 이름과 IP 매칭을 기억하는 저장소 역할을 하며, DNA resolution은 서버 이름으로부터 IP를 알아내는 행위를 뜻한다.

소켓(Socket)

컴퓨터 네트워킹에서 사용되는 개념으로, 사전적 의미와 같이 무언가 연결되는 연결부를 뜻하며 데이터 통신을 위한 엔드포인트이다. 소켓은 네트워크를 통해 데이터를 송수신하기 위한 인터페이스를 제공한다.

소켓 API

소켓은 클라이언트-서버 모델에서 사용되는데, 클라이언트 소켓과 서버 소켓으로 나뉜다. 클라이언트 소켓은 서버에 접속하고 데이터를 보내거나 받기 위한 역할이다. 서버 소켓은 클라이언트의 연결을 받아들이고, 클라이언트와의 데이터 통신을 관리한다.

클라이언트 소켓은 4가지 단계로 나뉜다.
1. 소켓을 생성한다(socket()).
2. 서버에 연결을 요청한다(connect()).
3. 서버 소켓에서 연결을 받으면 데이터를 받거나(recv()) 보낸다(send()).
4. 처리가 끝났다면 소켓을 닫는다(close()).

서버 소켓은 그보다 조금 많은 6가지 단계로 나뉜다.
1. 소켓을 생성한다.
2. 서버가 사용할 IP주소와 포트 번호를 생성한 소켓과 결합시킨다(bind).
3. 클라이언트 소켓으로부터의 연결 요청이 있었는지 확인한다(listen()).
4. 연결 요청을 수신한다(accept()). 하지만 여기서 연결 요청을 수신해서 클라이언트 소켓과 연결이 되는 것은 서버 소켓이 아니다. 서버 소켓은 연결 요청만 수신할 뿐, 연결되는 것은 accept API 내부에서 만들어지는 소켓이다. 고로 서버 소켓은 연결 요청 수신 후 또 다른 연결 요청 처리를 위해 대기하거나 서버 소켓을 닫는다.
5. 서버 소켓에서 연결을 받으면 데이터를 받거나(recv()) 보낸다(send()).
6. 처리가 끝났다면 소켓을 닫는다(close()).

참고한 자료 출처
CSAPP CHP 11
명지대 문대경 교수님 강의
https://stay-present.tistory.com/87
https://velog.io/@yoonvelog/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%9D%B8%ED%84%B0%EB%84%B7-%ED%86%B5%EC%8B%A0
https://velog.io/@inourbubble2/TCP-Header%EB%A5%BC-%EC%95%8C%EB%A9%B4-TCP%EB%A5%BC-%EC%9D%B4%ED%95%B4%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8B%A4
https://websecurity.tistory.com/93
https://www.ibm.com/docs/ko/aix/7.2?topic=protocol-tcpip-protocols
profile
> ㅁ <

0개의 댓글