• Home
  • About
    • Ara Jo photo

      Ara Jo

      Aspiring Backend Developer :)

    • Learn More
    • Email
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Book/성공과 실패를 결정하는 1% 네트워크 원리/2장

01 Sep 2021

Reading time ~8 minutes

1. 소켓을 작성한다

1. 프로토콜 스택의 내부 구성

network2-1.png
  • 네트워크 애플리케이션 : 아래로 데이터 송수신 등의 일을 의뢰
    • Socket 라이브러리와 그 안에 리졸버가 있음
  • OS : 프로토콜 스택
    • TCP : 브라우저나 메일 등 일반적인 애플리케이션
    • UDP : DNS 서버에 대한 조회 등 짧은 제어용 데이터를 송수신하는 경우
    • IP 프로토콜 : 데이터를 패킷단위로 송수신 (ICMP, ARP 프로토콜)
  • LAN 드라이버 : LAN 어댑터의 하드웨어 제어
  • LAN 어댑터 : 실제 송수신 동작, 즉 케이블에 대해 신호를 송수신하는 동작

2. 소켓의 실체는 통신 제어용 제어 정보

  • 프로토콜 스택의 내부에 제어 정보를 기록하는 메모리 영역이 있음
    • 통신 상대의 IP 주소, 포트 번호, 통신 동작의 진행 상태 등

프로토콜은 소켓에 기록된 제어 정보를 참조하며 움직임

3. Socket을 호출했을 때의 동작

network2-2.png
  1. 애플리케이션이 소켓을 만들 것을 의뢰하면 프로토콜 스택은 의뢰에 따라 한 개의 소켓을 만듦
  2. 소켓 한 개 분량의 메모리 영역을 확보
  3. 생성된 직후의 소켓은 초기 상태임을 나타내는 제어 정보를 소켓의 메모리 영역에 기록
  4. 다 만든 후 소켓을 나타내는 디스크립터 를 애플리케이션에 알려줌
    • 디스크립터 : 프로토콜 스택 내부의 소켓들 중 어떤 건지 알려주는 번호표

2. 서버에 접속한다

1. 접속의 의미

  • 소켓을 만든 직후는 상대의 정보를 모르므로 통신을 할 수 없음
  • 접속 : 통신 상대와의 사이에 제어 정보를 주고받아 소켓에 필요한 정보를 기록하고 데이터 송수신이 가능한 상태로 만드는 것
  • 클라이언트에서 이곳의 IP 주소는 xxx이고 포트번호는 xxx입니다. 데이터 송수신을 하고 싶은데 어떠세요? 라고 정보를 알려 통신하려는 클라이언트가 있다는 것을 서버측에 전달

2. 맨 앞부분에 제어 정보를 기록한 헤더를 배치한다

  • 제어정보
  1. 클라이언트와 서버가 서로 연락을 절충하기 위해 주고받는 정보
    • 접속 동작뿐 아니라 데이터를 송수신하는 동작, 연결을 끊는 동작도 포함하여 통신 전체에서 어떤 정보가 필요한지 검토하여 내용을 TCP 프로토콜 사양으로 규정
    • 주고받는 패킷의 맨 앞부분에 헤더 를 붙임 (TCP 헤더, 이더넷 헤더, IP 헤더 등)
  2. 소켓에 기록하여 프로토콜 스택의 동작을 제어하기 위한 정보
    • 애플리케이션에서 통지된 정보, 통신 상대로부터 받은 정보 등이 기록됨

3. 접속 동작의 실제

  1. 먼저 데이터 송수신 동작의 개시를 나타내는 제어 정보를 기록한 헤더를 만듦 (송신처와 수신처의 포트번호를 기록)
  2. 이를 통해 송신처가 되는 클라이언트 측의 소켓과 수신처가 되는 서버측의 소켓 지정
  3. 접속해야 하는 소켓이 어느 것인지 확실히 하고 컨트롤 비트인 SYN을 1로 초기화

⇒ 이렇게 TCP 헤더를 만들면 이것을 IP 담당 부분에 건네주어 송신하도록 의뢰

3. 데이터를 송수신한다

1. 프로토콜 스택에 HTTP 리퀘스트 메시지를 넘긴다

  • 프로토콜 스택은 받은 데이터를 곧바로 송신하는 것이 아니라 일단 자체의 내부에 있는 송신용 버퍼 메모리 영역에 저장함
    • 한 번의 송신 의뢰에서 건네주는 데이터의 길이가 매번 다르므로 어느 정도 데이터를 저장한 뒤 송수신 동작을 함
  • 프로토콜 스택은 내부에 타이머가 있어서 일정시간 이상 경과하면 패킷을 송신
    • 즉, 데이터가 모이지 않아도 일정 시간이 지나면 데이터를 보냄

⇒ 전자를 중시하면 패킷 길이 ⬆ 네트워크 이용 효율 ⬆ 버퍼에 머무는 만큼 지연 시간 ⬆
⇒ 후자를 중시하면 지연 시간 ⬇ 네트워크 이용 효율 ⬇

2. 데이터가 클 때는 분할하여 보낸다

  • 폼을 사용하여 긴 데이터를 보낼 경우 한 개의 패킷에 들어가지 않을만큼 HTTP 메시지가 길어질 수 있음
  • 데이터를 MSS의 크기에 맞게 분할해서 한 개씩 패킷에 넣어 송신
    • MSS : 헤더를 제외하고 한 개의 패킷으로 운반할 수 있는 TCP 데이터의 최대 길이

3. ACK 번호를 사용하여 패킷이 도착했는지 확인한다

  • 시퀀스 번호 : 데이터를 조각으로 분할할 때 조각이 통신 개시부터 몇 번째 바이트에 해당하는지를 세어둔 것, 악의적인 공격을 방지하기 위해 초기값을 난수값으로 설정 (SYN이 1이라는 것을 통해 초기값임을 인지)
  • 수신측에서는 패킷 전체 길이 - 헤더 길이 와 시퀀스 번호를 비교해서 패킷 누락 검증
  • ACK 번호 : 수신 확인 응답, 어디까지 수신했는지를 송신측에 알려주기 위한 용도

⇒ TCP는 이 두 가지를 이용해 데이터를 받은 것을 확인하고 확인할 때까지 송신한 패킷을 송신용 버퍼 메모리 영역에 보관해 둠

  • 송신한 데이터에 대응하는 ACK이 오지 않으면 패킷 재전송
  • 서버가 다운되는 등 아무리 보내도 데이터가 도착하지 않는 경우, TCP는 몇 번 다시 보낸 후 전망이 없는 것으로 보고 송신동작을 강제종료하고 애플리케이션에 오류 통지

4. 패킷 평균 왕복 시간으로 ACK 번호의 대기 시간을 조정한다

  • 타임아웃 값 : ACK 번호가 돌아오는 것을 기다리는 시간
  • TCP는 대기시간을 동적으로 변경하는 방법을 사용
    • 대기시간 ⬆ : 패킷을 다시 보내는 동작도 지연되어 속도 저하
    • 대기시간 ⬇ : ACK 돌아오기 전에 다시 보내야 하므로 낭비

5. 윈도우 제어 방식으로 효율적으로 ACK 번호를 관리한다

  • 한 개의 패킷을 보내고 ACK을 기다리는 시간이 낭비이므로 TCP는 윈도우 제어라는 방식을 이용해 송신과 ACK 번호 통지의 동작 실행
  • 윈도우 제어 : 한 개의 패킷을 보낸 후 ACK 번호를 기다리지 않고 차례대로 연속해서 복수의 패킷을 보내는 방법
    • 수신측의 능력을 초과해서 데이터를 송신하는 사태를 방지하기 위해 수신측에서 송신측에 수신 가능한 데이터 양(윈도우 사이즈)을 통지 후 수신측은 이 양을 초과하지 않도록 송신 동작 실행
network2-3.png

6. ACK 번호와 윈도우를 합승한다

  1. 윈도우 통지 : 수신측이 수신 버퍼에서 데이터를 추출하여 애플리케이션에 건네주었을 때
    • 수신측에서 애플리케이션에 데이터를 건네주고 수신 버퍼의 빈 영역이 늘어났을 때
  2. ACK 번호 통지 : 수신측에서 데이터를 받았을 때 내용을 조사하여 정상 수신을 확인할 수 있는 경우에만
    • 즉, 데이터를 수신한 후 즉시
  • 두 가지를 매번 따로따로 보내면 효율성이 저하됨 ⇒ 바로 보내지 않고 잠시 기다려서 동시에 일어난다면 두개를 한 패킷에 합승시키는 방식으로 패킷의 수를 줄임
  • ACK 통지가 연속하여 일어나면 최후의 것만 통지
  • 윈도우 사이즈 통지 역시 연속해서 일어나면 최후의 것만 통지

7. HTTP 응답 메시지를 수신한다

  • 브라우저는 Request 메시지 송신을 끝낸 뒤, Response 메시지를 받기 위해 read 호출
  1. 프로토콜 스택은 수신 버퍼에서 수신 데이터를 추출하여 애플리케이션에 건네줌
  2. 응답이 돌아올 때까지 잠시 보류
  3. 서버에서 응답 메시지의 패킷이 도착했을 때 그것을 수신하여 애플리케이션에 건네주는 작업 재개

4. 서버에서 연결을 끊어 소켓을 말소한다

1. 데이터 보내기를 완료했을 때 연결을 끊는다

  • 데이터 보내기를 완료한 쪽에서 연결끊기 단계에 들어감
  • 과정 (ex. 서버측)
  1. 서버측의 애플리케이션이 먼저 close를 호출
  2. 서버의 프로토콜 스택이 FIN(1) 을 송신
  3. FIN을 받은 클라이언트는 잘 받았다는 ACK번호를 서버에 반송
  4. 클라이언트 측 애플리케이션이 close 호출
  5. 클라이언트 프로토콜 스택이 FIN(1) 을 송신
  6. FIN을 받은 서버는 잘 받았다는 ACK번호를 클라이언트에 반송
  7. 대화 종료

2. 소켓을 말소한다

  • 대화가 끝나면 소켓을 사용하여 대화할 수 없으므로 소켓은 필요 없지만, 오동작을 막기 위해 잠시 기다린 후 소켓 말소
    • 오동작의 예 : FIN을 받은 클라이언트가 ACK을 보냈는데 돌아오지 않아 다시 FIN을 보내려고 하면 소켓이 이미 말소되고 없어서 새 소켓에 FIN이 도착할 수 있음
  • 기다리는 시간은 패킷을 다시 보낼 때 기다리는 시간만큼 기다림, 보통 몇 분 정도

3. 데이터 송수신 동작을 정리한다

  1. 소켓 작성
    • 서버측에서 애플리케이션이 동작하기 시작했을 때 소켓을 만들고 접속 대기 상태로 만듦
  2. 접속
    • 클라이언트에서 서버를 향해 접속 동작 실행
    • 클라이언트에서 서버에게 SYN(1)과 시퀀스 번호 초기값, 윈도우 값 보냄
    • 서버는 잘 받았다는 ACK 번호와 윈도우 값, SYN(1), 시퀀스 번호 초기값 보냄
    • 클라이언트에서 잘 받았다는 ACK 번호를 보냄
  3. 송수신 동작
    • TCP는 클라이언트가 보내는 리퀘스트 메시지를 조각으로 분할 후 헤더(시퀀스 번호)를 붙여서 보냄
    • 서버는 잘 받았다는 ACK 번호와 변경된 윈도우 값 보냄
    • TCP는 서버가 보내는 리스펀스 메시지를 조각으로 분할 후 헤더(시퀀스 번호)를 붙여서 보냄
    • 클라이언트는 잘 받았다는 ACK 번호와 변경된 윈도우 값 보냄
  4. 연결 끊기
    • 서버에서 FIN(1)을 보냄
    • 클라이언트에서 ACK 번호를 보냄
    • 클라이언트에서 FIN(1)을 보냄
    • 서버에서 ACK 번호를 보냄

5. IP와 이더넷의 패킷 송수신 동작

1. 패킷의 기본

  • 패킷 = 헤더 + 데이터
  • 헤더
    network2-4.png
    • MAC 헤더 : 이더넷용 헤더 (서브넷 안에 있는 이더넷이 중계 장치까지 패킷을 운반)
    • IP 헤더 : IP용 헤더 (IP가 목적지를 확인하여 다음 IP의 중계 장치를 나타냄)
  1. 송신처에서 목적지 액세스 대상 서버의 IP주소를 IP헤더에 기록
  2. IP는 이를 통해 수신처가 어느 방향에 있는지 조사 후 그 방향에 있는 다음 라우터의 이더넷 주소(MAC주소)를 MAC 헤더에 기록
  3. 허브에서 이더넷용 표와 헤더의 수신처 정보를 결합해 여러 허브를 순차적으로 경유한 뒤 다음 라우터에 도착
  4. 라우터에서 IP용 표와 IP 헤더의 수신처 정보를 결합해 다음 라우터를 판단하고 다음 라우터 주소를 MAC 헤더에 기록 후 다음 라우터에 송신
  5. 이것을 반복하면 패킷은 목적지에 도착

2. 수신처 IP 주소를 기록한 IP 헤더

  • IP 주소로 표시된 목적지까지 패킷을 전달할 때 사용하는 제어 정보
  • IP 담당 부분은 TCP로부터 TCP 헤더와 데이터 조각이 오면 IP 헤더를 만들어 TCP 헤더 앞에 붙임
    • 수신처 IP 주소 : TCP 담당 부분에서 통지된 통신 상대의 IP 주소 (애플리케이션이 통지)
    • 송신처 IP 주소 : 송신처가 되는 LAN 어댑터를 판단하여 주소 설정
    • 프로토콜 번호 : 패킷에 들어간 내용물이 어디에서 의뢰받은 것인지를 나타내는 값

3. ARP 프로토콜

  • ARP : IP 주소로 MAC 주소를 찾아주는 프로토콜
  • 이더넷에 연결된 라우터들에게 브로드캐스트하는 방식으로 MAC 주소를 알아냄

4. 이더넷용 MAC 헤더

  • 이더넷 등의 LAN을 사용하여 가장 가까운 라우터까지 패킷을 운반할 때 사용하는 제어 정보
  • IP 담당 부분은 MAC 헤더를 만들어 IP 헤더 앞에 붙임
    • 수신처 MAC 주소 : 패킷을 건네주는 상대의 MAC 주소
    • 송신처 MAC 주소 : 송신한 측의 MAC 주소, 자체 LAN 어댑터의 MAC 주소
    • 이더 타입 : 사용하는 프로토콜의 종류

5. 이더넷

  • 이더넷 : 다수의 컴퓨터가 여러 상대와 자유롭게 적은 비용으로 통신하기 위해 고안된 통신 기술
  • 성질
    1. 수신처 MAC 주소에 따라 패킷이 누구에게 갈 것인지를 앎
    2. 송신처 MAC 주소에 따라 누가 송신한 것인지를 앎
    3. 이더 타입에 의해 패킷의 내용물로 무엇이 들어있는지를 앎

6. 패킷에 3개의 제어용 데이터 추가

  1. 프리앰블
  2. 스타트 프레임 딜리미터
  3. 프레임 체크 시퀀스(FCS) : 오류 검출용 데이터
    • 패킷을 운반하는 도중에 잡음 등의 영향으로 파형이 흐트러져 데이터가 변한 경우를 검출하기 위해 사용
    • 32비트의 비트열로, CRC(Cyclic Redundancy Check)를 바탕으로 계산한 것
    • 계산한 결과와 일치하는지를 통해 데이터 변화한 사실 검출

7. 허브

  1. 리피터 허브 : 반이중 모드
    • 어떤 시점에서 송신과 수신 중 한쪽만 가능한 것
  2. 스위칭 허브 : 전이중 모드
    • 송신 동작과 수신 동작을 동시에 병행하여 실행할 수 있는 것

6. UDP 프로토콜을 이용한 송수신 동작

1. 수정 송신이 필요없는 데이터의 송신은 UDP가 효율적이다

  • TCP
    • ✅ 데이터를 확실하면서도 효율적으로 전달
    • ❌ 구조가 복잡함
  • 데이터를 한 번에 다 보내고 수신 확인 응답을 한 번만 받는 방법
  • UDP
    • 수신확인이나 윈도우가 없어서 데이터 송수신 전 제어정보를 주고받을 필요가 없음
    • 접속이나 연결 끊기 단계가 없음
    • IP헤더의 IP주소와 UDP 헤더의 포트 번호를 결합하여 상대 찾음
    • ✅ 송수신 간단
    • ❌ 데이터 안정성이 보장되지 않음
  • UDP 헤더
    • 송신처 포트 번호
    • 수신처 포트 번호
    • 데이터 길이
    • 체크섬 : 오류 유무를 검사

2. UDP를 사용하는 경우

  • 수신확인이 안 오면 전부 다 다시 보내기 때문에 보내려는 패킷이 적은 경우는 효율적
    • DNS 서버에 대한 조회 등 제어용으로 실행하는 정보 교환
  • 데이터의 손실보다 속도가 더 중요한 경우
    • 음성이나 영상 데이터는 정해진 시간 안에 데이터를 건네주어야 하므로 빠른 UDP를 사용


csstudynetworkbook Share Tweet +1