ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [1%의 네트워크 원리] 2장 : TCP/IP의 데이터를 전기 신호로 만들어 보낸다
    책/성공과 실패를 결정하는 1%의 네트워크 원리 2024. 2. 25. 21:37
    반응형

    STORY 1. 소켓을 작성한다

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

    애플리케이션 네트워크 애플리케이션 (웹 브라우저 등)
      Socket 라이브러리 (리졸버)
    OS 프로토콜 스택 (TCP, UDP)
      프로토콜 스택 (IP, ICMP, ARP)
    드라이버 소프트웨어 LAN 드라이버 (LAN 어댑터 제어)
    하드웨어 LAN 어댑터

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

    • 소켓 - 제어 정보를 기록한 메모리 영역
      • 통신 상대의 IP 주소, 포트 번호, 통신 동작의 진행 상태 등
    • 프로토콜 스택은 소켓에 기록된 제어 정보를 참조하며 동작

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

    • 프로토콜 스택은 소켓 한개 분량의 메모리 영역을 확보한다.
    • 그 다음 초기 상태를 나타내는 제어 정보를 소켓에 기록
    • 소켓이 만들어지면 디스크립터를 애플리케이션에 알려줌
    • 프로토콜 스택은 디스크립터를 통해 어느 소켓인지를 판별할 수 있고, 이를 통해 애플리케이션에서 일일이 통신 상태에 대해 통지할 필요가 없어진다.

    STORY 2. 서버에 접속한다

    1. 접속의 의미

    • 소켓을 만든 직후에는 아무것도 기록되어 있지 않아 상대가 누구인지도 모름
    • 그래서 connect를 통해 IP 주소, 포트 번호 등을 클라이언트에서 서버로 전송하게 됨
    • 이러한 제어 정보를 받게 되면 데이터를 송수신할수 있는 상태가 됨

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

    • TCP 헤더 (20바이트 ~)
    송신처 포트 번호 16비트 패킷을 발신한 측의 프로그램의 포트 번호
    수신처 포트 번호 16비트 패킷을 받는 상대 프로그램의 포트 번호
    시퀀스 번호 32 맨 앞 위치의 데이터 바이트 해당 인덱스
    ACK 번호 32 몇 바이트까지 수신측에 도착했는지
    데이터 오프셋 4 데이터 부분이 어디부터 시작하는지 → 헤더의 길이
    사용하지 않음 6 사용 X
    컨트롤 비트 6 - URG : 긴급 포인터 유효
        - ACK : ACK 필드가 유효
        - PSH : flush 동작에 의해 송신된 데이터임을 나타냄
        - RST : 강제 종료, 이상 종료 시 사용
        - SYN : 송신, 수신 측에서 일련번호 서로 확인
        - FIN : 연결 끊기
    윈도우 16 수신할 수 있는 윈도우 사이즈
    체크섬 16 오류 유무
    긴급 포인터 16 긴급 처리 데이터 위치 나타냄
    옵션 가변 길이 추가 정보
    - 각 계층마다 헤더가 존재한다.    
    - 제어 정보    
    - 헤더에 기입되는 정보    
    - 소켓에 기록되는 정보(프로토콜 스택의 메모리 영역)    

    3. 접속 동작의 실태

    1. connect() 를 호출한다.
    2. 데이터 송 수신 동작의 게시를 나타내는 제어정보를 기록한 헤더를 만듦
    3. 송신처, 수신처의 포트 번호, SYN 을 설정
    4. 서버에게 보내고, 서버의 TCP 담당 부분이 이를 확인
    5. 서버 또한 SYN, ACK 비트를 1로 하고 이를 보냄
    6. 클라이언트가 ACK을 보냄
      • 이를 3-way handshake라고 함
      • 커넥션이 연결되고, 이는 close()를 호출할 때까지 지속됨

    STORY 3. 데이터를 송수신한다

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

    • 데이터 송수신은 write()를 호출하여 송신 데이터를 프로토콜 스택에 건네주는 것부터 시작
    • 받은 데이터를 바로 전송하는 것이 아닌 송신용 버퍼 메모리 영역에 저장하고, 다음 데이터를 기다림
    • 받은 데이터를 곧바로 보내면 작은 패킷을 자주 보냄 → 네트워크 이용 효율 저하 → 어느 정도 데이터를 저장하고 송수신
      • 판단 근거 1 : 한 패킷에 저장할 수 있는 데이터의 크기 (MTU)
        • 헤더를 제외한 데이터의 최대 길이 : MSS → 이를 근거로 판단
      • 판단 근거 2 : 타이밍
        • 애플리케이션의 송신 속도가 느려지는 경우 MSS에 가깝게 데이터를 저장하는데 시간 오래 소요 → 데이터가 다 모이지 않아도 적절한 시간에 전송 → 내부 타이머를 통해 일정 시간 경과 시 패킷 송신
      • 이 둘을 잘 분배해서 생각해야함
        • 전자를 중시하면 네트워크 이용 효율은 높아지지만 송신 동작 지연
        • 후자를 중시하면 지연은 적어지지만 네트워크 이용 효율 감소

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

    • 데이터가 너무 큰 경우 (MSS 초과 시)
      • 송신 버퍼에 들어있는 데이터를 차례대로 MSS 크기에 맞게 분할
      • 분할된 데이터들에 각각 TCP 헤더를 붙여 전송

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

    • 데이터를 분할할 때 조각이 통신 개시부터 따져서 몇번째 바이트에 해당하는지 기록 → 시퀀스 번호
    • 시퀀스 번호를 통해 데이터 누락 확인 가능
    • 누락 없는 걸 확인한 서버는 몇 번째 바이트까지 수신했는지를 클라이언트에게 알려줌 → ACK 번호
      • 이러한 동작을 수신 확인 응답이라고 부름
    • 시퀀스 번호는 임의의 난수로 시작 → 무조건 1로 시작하면 해킹 위험
      • 이는 처음 연결 수립 때 SYN으로 서버에게 알려줌
    • TCP는 양방향 → 연결 수립 때 SYN → SYN + ACK → ACK 을 통해 서로의 시작 시퀀스 번호를 알려줌
    • 데이터 송신 후 확인 응답(ACK) 이 올 때까지 송신용 버퍼 메모리에서 없애지 않음
      • ACK이 안오면 패킷 다시 보내기 위해서
    • 이러한 구조 덕분에 다른 계층에서는 회복 조치를 취하지 않음
      • 그러나 케이블 분리 등 물리적인 문제 발생 시 무한정 보내는 것을 막기 위해 몇번 다시 보낸후에도 ACK 안오면 송신 동작 강제 종료

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

    • ACK 번호가 돌아오는 것을 기다리는 시간 → 타임아웃 값
    • 타임아웃 시간을 상수로 정하면 네트워크 상황에 따라 달라짐 → 적절하지 않음
    • 그래서 TCP는 대기 시간을 동적으로 정함
      • 데이터 송신 시 항상 ACK이 오는 시간을 체크하고, 이를 토대로 대기시간을 늘리거나 줄임

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

    • 윈도우 제어 → 한개의 패킷을 보낸 후 ACK을 기다리지 않고 차례대로 연속해서 복수의 패킷 보냄 → ACK 기다리는 시간 낭비 없앰
    • 문제
      • 핑퐁 방식 (하나 보내고 기다리다가 ACK 오면 하나 보내기) : 수신측 버퍼가 넘칠 일이 없음
      • 윈도우 방식
        • 수신 측에서도 ACK 점검, 데이터 병합 및 애플리케이션 계층 전송이 이루어져야 하므로 수신 버퍼가 존재
        • 애플리케이션으로 보내는 속도보다 수신받는 데이터가 더 많으면 버퍼 넘침 → 넘치는 데이터는 버려지므로 오류처럼 간주됨
    • 피하는 방법
      • 수신측에서 송신측에 수신 가능한 데이터 양을 통지
    • 수신 측에서 수신 처리 끝나고 버퍼 빈자리 생기면 이를 송신측에 윈도우 필드를 통해 통지
    • 실제 동작은 시퀀스 번호 및 ACK 번호와 마찬가지로 양방향
    • 수신 가능한 최대 데이터 양 → 윈도우 사이즈

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

    • 윈도우 번호 통지가 필요할 때 : 애플리케이션에 데이터 넘기고 수신 버퍼에 공간이 생길 때
    • ACK 번호 통지가 필요할 때 : 수신측에서 데이터 받았을 때 정상 수신임을 확인할 때
    • 원래의 경우 ACK 번호 통지 후 윈도우 번호 통지 → 따로따로 보내게 됨 → 이러면 비효율적
    • 수신측에서 소켓을 바로 보내지 않고 기다림
      • 기다리는 사이에 통지 동작이 또 발생하면 양쪽을 상승시켜서 한개의 패킷으로 묶어 보냄
      • 통지 연속 발생 시 (윈도우든 ACK이든) 마지막 부분만 통지해서 보내면 됨

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

    • 브라우저가 리퀘스트 메시지 송신을 의뢰한 뒤, read() 프로그램 호출 → 서버에서 돌아오는 응답 메시지를 기다림
    • 응답 메시지가 올때까지 기다림
    • 수신한 데이터 조각과 TCP 헤더의 내용을 조사하여 누락 확인
    • 문제 없으면 ACK 보내고, 데이터 조각을 모아 애플리케이션에 돌려줌

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

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

    • 데이터 보내기를 완료한 쪽에서 연결 끊기 단계에 들어감
    • 서버측에서 연결 끊기 단계에 들어가는 것으로 간주함
      1. 서버측 애플리케이션이 먼저 close() 호출 → FIN을 클라이언트로 보냄
      2. 클라이언트가 서버로 ACK을 보냄
      3. 클라이언트 애플리케이션에서 read() 호출 후 수신 버퍼 잔여 데이터 받음
      4. 다 받으면 close() 호출 → 서버로 FIN 보냄
      5. 서버가 ACK 보냄

    2. 소켓을 말소한다

    • 소켓을 바로 말소하지 않고 잠시 기다린 뒤 말소함
      1. 클라이언트가 FIN 송신
      2. 서버가 ACK 송신
      3. 서버가 FIN 송신
      4. 클라이언트가 ACK 송신
    • 이 경우에서 서버가 ACK을 못 받은 경우 다시 FIN을 보내게 됨
    • 그 때 이미 클라이언트 소켓이 말소되고 새로운 소켓이 이를 받게됨
    • 그러면 그 소켓은 시작하자마자 종료하게 됨
    • 그래서 몇 분 기다린 뒤 소켓을 말소함

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

    1. 소켓 작성
      • 이 때는 패킷이 흐르지 않음
    2. 접속 동작 단계
      1. 클라이언트에서 서버로 SYN + 시퀀스 번호 + 윈도우 사이즈 전송
      2. 서버에서 클라이언트로 SYN + ACK + 시퀀스 번호 + 윈도우 사이즈 전송
      3. 클라이언트에서 서버로 ACK 번호 전송
    3. 송수신 단계
      • 요청하는 쪽이 시퀀스 번호 + 데이터를 보내면 받는 쪽에서 ACK 번호와 윈도우 사이즈를 보냄
    4. 연결 끊기 단계
      1. 종료하는 쪽이 FIN 보냄
      2. 상대방이 ACK 보냄
      3. 이후 상대방이 FIN 보냄
      4. 종료하는 쪽이 ACK 보냄

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

    1. 패킷의 기본

    • 패킷은 헤더와 데이터 두 부분으로 구성
      1. 송신처에서 패킷 생성
      2. 가장 가까운 중계 장치에 송신
      3. 중계 장치에서 목적지 판단 ← 어느 수신처가 어느 방향에 있는지에 대한 표 사용
      4. 다음 중계 장치로 이동
      5. 이를 반복하여 수신처로 도착
    • 송신처와 수신처의 기기를 묶어 엔드노드라고 부름
    • 허브는 이더넷의 규칙에 따라 운반(MAC 헤더), 라우터는 IP의 규칙에 따라 운반(IP 헤더)
    • MAC 헤더는 라우터가 패킷을 중계할 때 바뀌지만, IP 헤더는 바뀌지 않음

    2. 패킷 송수신 동작의 개요

    • IP 담당 부분은 MAC 헤더와 IP 헤더를 붙여 하드웨어(이더넷, 무선 LAN)로 전송
    • TCP 헤더와 데이터 조각을 한 덩어리의 바이너리 데이터로 봄 → 내용을 보지 않고 단순히 송신, 수신만을 담당함

    3. 수신처 IP 주소를 기록한 IP 헤더를 만든다

    • 수신처 IP 주소 : 애플리케이션에서 지정한 IP 주소로써, 잘못되면 애플리케이션 책임
    • 송신처 IP 주소
      • 클라이언트 PC는 보통 LAN 어댑터가 하나이므로 컴퓨터에 할당된 IP 주소라고 해도 됨
      • 그러나 LAN 어댑터가 여러개라면 이 개념으로는 부족
      • 라우터가 다음 라우터를 결정하는 것처럼 라우팅 테이블을 통해 송신처 IP를 결정

    4. 이더넷용 MAC 헤더를 만든다

    • MAC 헤더
      • 수신처 MAC 주소
        • 이 시점에서 라우팅 테이블을 통해 상대 IP를 알아냄
        • 그러나 MAC 주소는 아직 알고 있는 상태가 아님 → ARP 사용
      • 송신처 MAC 주소
      • 이더 타입

    5. ARP로 수신처 라우터의 MAC 주소를 조사한다

    • ARP
      • 요청 → 브로드캐스트
      • 응답 → 유니캐스트
    • 매번 요청 보내면 비효율 → ARP 캐시 존재
    • 몇 분 경과시 무조건 삭제

    6. 이더넷의 기본

    • 원형
      • 모두에게 전기 신호 전송
      • 그 중 자기 거인 것은 받고, 나머지 장치들은 다 버림
    • 현재
      • 스위칭 허브를 통해 원하는 부분에만 신호가 감

    7. IP 패킷을 전기나 빛의 신호로 변환하여 송신한다

    • 송신할 때 디지털 데이터를 바로 보낼 수 없다 → 이를 전기나 빛 신호로 바꿔야함
      • 이를 LAN 어댑터가 함
    • LAN 어댑터 초기화
      • MAC 회로에 MAC 주소 설정
      • LAN 어댑터 ROM에는 전 세계에서 중복되지 않는 MAC 주소가 제조할 때 기록되어 있음

    8. 패킷에 3개의 제어용 데이터를 추가한다

    • IP 레이어에서 데이터를 받으면 먼저 LAN 어댑터의 버퍼 메모리에 복사
    • 송신할 준비가 되면 버퍼 메모리에서 데이터 읽어옴
    • 맨 앞부터 프리앰블, 스타트 프레임 딜리미터를 붙이고, 패킷의 맨 끝에 FCS(오류 검출용) 붙임
    • 프리앰블
      • 패킷을 읽을 때의 타이밍을 잡기 위한 것
    • 스타트 프레임 딜리미터
      • 패킷의 시작을 나타내는 표시

    9, 10 생략

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

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

    2. 제어용 짧은 데이터

    • DNS 서버 조회 등 제어용 실행 정보 교환은 한개의 패킷으로 끝나는 경우 많음 → UDP가 효율적
    • 오류 발생 시 회답이 돌아오지 않을 것이므로 다시 보내면 됨

    3. 음성 및 동영상 데이터

    • 주로 UDP 사용
    • 패킷 손실이 치명적이지 않음

     

     

    https://product.kyobobook.co.kr/detail/S000000559964

    반응형
Designed by Tistory.