... | ... | @@ -678,49 +678,51 @@ TCP는 분리된 메시지를 보내는 것이 아니라, 데이터를 바이트 |
|
|
6. Congestion control
|
|
|
네트워크 정체를 방지하기 위해 receive window와 별도로 congestion window를 사용하는데 이는 네트워크에 유입되는 데이터양을 제한하기 위해서이다. Receive window와 마찬가지로 congestion window가 허용하는 바이트 수만큼 데이터를 전송한다. Flow control과 달리 송신자가 단독으로 구현한다.
|
|
|
|
|
|
**데이터 송신 시 TCP/IP 네트워크 스택의 레이어 별 동작과정**
|
|
|

|
|
|
네트워크 스택은 크게 유저, 커널, 디바이스 영역으로 나눌 수 있다. 유저와 커널 영역의 작업은 CPU가 수행한다. 그리고 디바이스 영역과 구별하기 위해 유저와 커널 영역은 호스트라고 부른다. 디바이스는 패킷을 송수신하는 NIC(Network Interface Card)이다. 흔히 랜카드라고 부른다.
|
|
|
**데이터 송신 시 TCP/IP 네트워크 스택의 레이어 별 동작과정**
|
|
|
|
|
|
먼저, 유저 영역에서 어플리케이션이 전송할 데이터를 만들고 write 시스템 콜을 호출해서 데이터를 보낸다. 그럼 미리 생성/연결된 소켓을 통해서 데이터 송신을 요청한다. 시스템 콜이 호출되면 커널 영역으로 전환된다.
|
|
|

|
|
|
|
|
|
리눅스나 유닉스 같은 POSIX 계열 운영체제에서는 소켓을 파일의 한 종류로 보고, file descriptor로 어플리케이션에 노출한다. 파일 레이어는 이 file descriptor가 유효한지 확인만 하고 소켓 함수를 호출한다.
|
|
|
네트워크 스택은 크게 유저, 커널, 디바이스 영역으로 나눌 수 있다. 유저와 커널 영역의 작업은 CPU가 수행한다. 그리고 디바이스 영역과 구별하기 위해 유저와 커널 영역은 호스트라고 부른다. 디바이스는 패킷을 송수신하는 NIC(Network Interface Card)이다. 흔히 랜카드라고 부른다.
|
|
|
|
|
|
커널 소켓은 send socket buffer와 receive socket buffer 두 개의 버퍼를 가지고 있다. Write 시스템 콜이 호출되면 유저 영역의 데이터가 커널 메모리로 복사되고, send socket buffer의 뒷부분에 추가된다. 기존에 보내고 있던 데이터 뒤에 붙여서 전송 순서를 지키기 위함이다. 다음으로 TCP를 호출한다.
|
|
|
먼저, 유저 영역에서 어플리케이션이 전송할 데이터를 만들고 write 시스템 콜을 호출해서 데이터를 보낸다. 그럼 미리 생성/연결된 소켓을 통해서 데이터 송신을 요청한다. 시스템 콜이 호출되면 커널 영역으로 전환된다.
|
|
|
|
|
|
소켓과 연결된 TCB(TCP Control Block) 구조체가 있다. TCB에는 TCP 연결 처리에 필요한 정보가 있다. TCB에는 connection state, receive window, congestion window, sequence 번호, 재전송 타이머 등이 있다.
|
|
|
리눅스나 유닉스 같은 POSIX 계열 운영체제에서는 소켓을 파일의 한 종류로 보고, file descriptor로 어플리케이션에 노출한다. 파일 레이어는 이 file descriptor가 유효한지 확인만 하고 소켓 함수를 호출한다.
|
|
|
|
|
|
TCP는 현재의 TCP State가 데이터 전송이 가능하면, 새로운 TCP Segment를 만든다. Flow Control과 같은 이유로 데이터 전송이 불가능하면 시스템 콜이 끝나고, 유저모드로 되돌아간다.
|
|
|
커널 소켓은 send socket buffer와 receive socket buffer 두 개의 버퍼를 가지고 있다. Write 시스템 콜이 호출되면 유저 영역의 데이터가 커널 메모리로 복사되고, send socket buffer의 뒷부분에 추가된다. 기존에 보내고 있던 데이터 뒤에 붙여서 전송 순서를 지키기 위함이다. 다음으로 TCP를 호출한다.
|
|
|
|
|
|
TCP Segment에는 TCP 헤더와 페이로드가 있다. 페이로드에는 send socket buffer에 있는 ACK를 받지 않은 데이터가 담겨있다. 페이로드의 최대 길이는 receive window, congestion window, MSS(Maximun Segment Size) 중 최대 값이다.
|
|
|
소켓과 연결된 TCB(TCP Control Block) 구조체가 있다. TCB에는 TCP 연결 처리에 필요한 정보가 있다. TCB에는 connection state, receive window, congestion window, sequence 번호, 재전송 타이머 등이 있다.
|
|
|
|
|
|
그리고 TCP checksum을 계산한다. 이 checksum 계산에서는 pseudo 헤더 정보(IP 주소들, segment 길이, 프로토콜 번호)를 포함시킨다.
|
|
|
TCP는 현재의 TCP State가 데이터 전송이 가능하면, 새로운 TCP Segment를 만든다. Flow Control과 같은 이유로 데이터 전송이 불가능하면 시스템 콜이 끝나고, 유저모드로 되돌아간다.
|
|
|
|
|
|
생성된 TCP segment는 IP 레이어로 내려간다. IP 레이어에서는 TCP Segment에 IP 헤더를 추가하고 IP 라우팅을 한다. IP 레이어에서 IP 헤더 checksum을 계산하여 덧붙인 후, Ethernet 레이어로 데이터를 보낸다.
|
|
|
TCP Segment에는 TCP 헤더와 페이로드가 있다. 페이로드에는 send socket buffer에 있는 ACK를 받지 않은 데이터가 담겨있다. 페이로드의 최대 길이는 receive window, congestion window, MSS(Maximun Segment Size) 중 최대 값이다.
|
|
|
|
|
|
Ethernet 레이어는 ARP(Address Resolution Protocol)를 사용해서 전송될 장비 MAC 주소를 찾는다. 그리고 Ethernet 헤더를 패킷에 추가한다. 이때 Ethernet 표준에 따라 IFG(Inter-Frame Gap), preamble, 그리고 CRC를 패킷에 추가한다. IFG, preamble은 패킷의 시작을 판단하기 위해 사용하고(네트워킹 용어로는 framing), CRC는 데이터 보호를 위해 사용한다(TCP, IP checksum과 같은 용도이다). Ethernet 헤더까지 붙으면 호스트 패킷이 완성된다.
|
|
|
그리고 TCP checksum을 계산한다. 이 checksum 계산에서는 pseudo 헤더 정보(IP 주소들, segment 길이, 프로토콜 번호)를 포함시킨다.
|
|
|
|
|
|
IP 라우팅을 하면 전송될 장비의 IP 주소와 해당 IP로 패킷을 전송할 때 사용하는 인터페이스(NIC)를 알게된다. 그러면 드라이버는 그 NIC를 호출한다. 드라이버는 NIC 제조사가 정의한 드라이버-NIC 통신 규약에 따라 패킷 전송을 요청한다.
|
|
|
생성된 TCP segment는 IP 레이어로 내려간다. IP 레이어에서는 TCP Segment에 IP 헤더를 추가하고 IP 라우팅을 한다. IP 레이어에서 IP 헤더 checksum을 계산하여 덧붙인 후, Ethernet 레이어로 데이터를 보낸다.
|
|
|
|
|
|
NIC는 패킷 전송을 요청받고, 메인 메모리에 있는 패킷을 자신의 메모리로 복사하고, 네트워크 선으로 전송한다. 그리고 패킷 전송이 완료되면 NIC는 호스트 CPU에 인터럽트를 발생시킨다. 그럼 운영체제는 인터럽트 핸들러를 호출한다. 인터럽트 핸들러는 전송된 패킷(송신 결과)을 운영체제에 반환한다.
|
|
|
Ethernet 레이어는 ARP(Address Resolution Protocol)를 사용해서 전송될 장비 MAC 주소를 찾는다. 그리고 Ethernet 헤더를 패킷에 추가한다. 이때 Ethernet 표준에 따라 IFG(Inter-Frame Gap), preamble, 그리고 CRC를 패킷에 추가한다. IFG, preamble은 패킷의 시작을 판단하기 위해 사용하고(네트워킹 용어로는 framing), CRC는 데이터 보호를 위해 사용한다(TCP, IP checksum과 같은 용도이다). Ethernet 헤더까지 붙으면 호스트 패킷이 완성된다.
|
|
|
|
|
|
**데이터 수신 시 TCP/IP 네트워크 스택의 레이어 별 동작과정**
|
|
|

|
|
|
패킷이 외부에서 도착하면 NIC가 패킷을 자신의 메모리에 기록한다. CRC 검사로 패킷에 손상이 없는지 확인하고, 호스트의 메모리 버퍼로 전송한다. 이 메모리 버퍼는 드라이버가 커널에 요청하여 패킷 수신용으로 미리 할당한 메모리이다. 이 버퍼가 없으면 NIC는 패킷을 버릴 수 있다. 이를 packet drop이라하고, packet drop을 방지하기 위해 흐름 제어를 한다.
|
|
|
IP 라우팅을 하면 전송될 장비의 IP 주소와 해당 IP로 패킷을 전송할 때 사용하는 인터페이스(NIC)를 알게된다. 그러면 드라이버는 그 NIC를 호출한다. 드라이버는 NIC 제조사가 정의한 드라이버-NIC 통신 규약에 따라 패킷 전송을 요청한다.
|
|
|
|
|
|
패킷을 호스트 메모리로 전송한 후 NIC가 운영체제에 인터럽트를 보낸다. 드라이버는 수신된 패킷을 보고 자신이 처리할 수 있는 패킷인지 검사한다. 이때까지는 제조사가 정의한 드라이버-NIC 통신 규약을 사용한다.
|
|
|
NIC는 패킷 전송을 요청받고, 메인 메모리에 있는 패킷을 자신의 메모리로 복사하고, 네트워크 선으로 전송한다. 그리고 패킷 전송이 완료되면 NIC는 호스트 CPU에 인터럽트를 발생시킨다. 그럼 운영체제는 인터럽트 핸들러를 호출한다. 인터럽트 핸들러는 전송된 패킷(송신 결과)을 운영체제에 반환한다.
|
|
|
|
|
|
드라이버가 상위 레이어로 패킷을 전달할 때, 운영체제게 이해할 수 있도록 패킷을 운영체제가 사용하는 패킷 구조체로 포장한다. 드라이버는 포장한 패킷 구조체를 상위 레이어로 전달한다.
|
|
|
**데이터 수신 시 TCP/IP 네트워크 스택의 레이어 별 동작과정**
|
|
|
|
|
|
Ethernet 레이어에서도 패킷이 올바른지 검사한다. 패킷이 올바르면 Ethernet 헤더를 제거하고 IP 레이어로 패킷을 전달한다.
|
|
|

|
|
|
|
|
|
IP 레이어에서도 IP 헤더 checksum을 확인해서 패킷이 올바른지 검사한다. IP 라우팅을 해서 패킷을 현재 장비에서 처리해야 하는지, 다음 장비로 전송해야 하는지 판단한다. 현재 장비에서 처리해야 하면, IP 헤더를 제거하고 TCP 레이어로 패킷을 전달한다.
|
|
|
패킷이 외부에서 도착하면 NIC가 패킷을 자신의 메모리에 기록한다. CRC 검사로 패킷에 손상이 없는지 확인하고, 호스트의 메모리 버퍼로 전송한다. 이 메모리 버퍼는 드라이버가 커널에 요청하여 패킷 수신용으로 미리 할당한 메모리이다. 이 버퍼가 없으면 NIC는 패킷을 버릴 수 있다. 이를 packet drop이라하고, packet drop을 방지하기 위해 흐름 제어를 한다.
|
|
|
|
|
|
TCP 레이어에서도 checksum을 확인해서 패킷이 올바른지 검사한다. 그 다음 TCB를 찾는다. TCB를 찾으면 프로토콜을 수행해서 받은 패킷을 처리한다. 데이터를 해당 TCB에 속한 소켓의 receive socket buffer에 추가한다. 그 후 TCP 상태에 따라서 새로운 TCP 패킷(ACK 등)을 전송할 수 있다. 이렇게 수신 패킷 처리 과정이 끝난다.
|
|
|
패킷을 호스트 메모리로 전송한 후 NIC가 운영체제에 인터럽트를 보낸다. 드라이버는 수신된 패킷을 보고 자신이 처리할 수 있는 패킷인지 검사한다. 이때까지는 제조사가 정의한 드라이버-NIC 통신 규약을 사용한다.
|
|
|
|
|
|
이후 어플리케이션이 read 시스템 콜을 호출하면 커널 영역으로 전환되고, socket buffer에 있는 데이터를 유저 공간의 메모리로 복사해 간다. 복사가 끝나면 복사한 데이터는 socket buffer에서 제거하고 TCP를 호출한다. TCP는 socket buffer에 새로운 공간이 생겼기 때문에 receive window를 증가시킨다. 그리고 프로토콜 상태에 따라서 패킷을 전송한다.
|
|
|
드라이버가 상위 레이어로 패킷을 전달할 때, 운영체제게 이해할 수 있도록 패킷을 운영체제가 사용하는 패킷 구조체로 포장한다. 드라이버는 포장한 패킷 구조체를 상위 레이어로 전달한다.
|
|
|
|
|
|
Ethernet 레이어에서도 패킷이 올바른지 검사한다. 패킷이 올바르면 Ethernet 헤더를 제거하고 IP 레이어로 패킷을 전달한다.
|
|
|
|
|
|
IP 레이어에서도 IP 헤더 checksum을 확인해서 패킷이 올바른지 검사한다. IP 라우팅을 해서 패킷을 현재 장비에서 처리해야 하는지, 다음 장비로 전송해야 하는지 판단한다. 현재 장비에서 처리해야 하면, IP 헤더를 제거하고 TCP 레이어로 패킷을 전달한다.
|
|
|
|
|
|
TCP 레이어에서도 checksum을 확인해서 패킷이 올바른지 검사한다. 그 다음 TCB를 찾는다. TCB를 찾으면 프로토콜을 수행해서 받은 패킷을 처리한다. 데이터를 해당 TCB에 속한 소켓의 receive socket buffer에 추가한다. 그 후 TCP 상태에 따라서 새로운 TCP 패킷(ACK 등)을 전송할 수 있다. 이렇게 수신 패킷 처리 과정이 끝난다.
|
|
|
|
|
|
이후 어플리케이션이 read 시스템 콜을 호출하면 커널 영역으로 전환되고, socket buffer에 있는 데이터를 유저 공간의 메모리로 복사해 간다. 복사가 끝나면 복사한 데이터는 socket buffer에서 제거하고 TCP를 호출한다. TCP는 socket buffer에 새로운 공간이 생겼기 때문에 receive window를 증가시킨다. 그리고 프로토콜 상태에 따라서 패킷을 전송한다.
|
|
|
|
|
|
|
|
|
12. **LINQ 결과인 IEnumerable<T>를 for 문으로 루프 돌때, breakpoint 걸어서 확인해보기**
|
... | ... | |