profile image

L o a d i n g . . .

article thumbnail image
Published 2023. 10. 20. 17:56
728x90

본 포스팅에서는 Naver D2의 "TCP/IP 네트워크 스택 이해하기" 문서와 RFC 793(Transmission Control Protocol)를 참조해서 TCP에 대해 살펴보겠습니다. 

TCP(Transmission Control Protocol)란?  

우선 TCP는 어떤 성격의 프로토콜인지 살펴보겠습니다. 

TCP의 특성 

Connection oriented 

TCP는 통신하기 위해 우선 프로세스 간 연결(connection)을 맺어야 합니다. RFC 문서는 connection을 다음과 같이 정의합니다. 

The reliability and flow control mechanisms described above require that TPCs initialize and maintain certain status information for each data stream. The combination of this information, including sockets, sequence numbers, and window sizes, is called a connection. 

 

즉, connection이란 TCP의 data stream과 관련된 정보의 집합(pair of sockets, sequence number, window size)을 의미합니다. 또한 "pair of sockets"를 해당 connection의 식별자로 사용합니다. 

Bidirectional byte stream 

TCP는 양방향 통신)이 가능하며 byte stream을 활용합니다. RFC 문서에서는 socket을 활용한 통신은 full-duplex(양방향 통신)라고 명시하고 있습니다. 

In-order delivery 

수신자는 송신자가 보낸 순서대로 데이터를 받습니다. 이를 위해 sequence number을 사용합니다. Sequence number는 전송된 데이터의 바이트 수만큼 증가합니다. 예를 들어 1400 bytes의 데이터가 송신되면 sequence number는 1400만큼 증가합니다. 

Reliability through ACK 

수신자는 데이터를 수신 후 "데이터 수신 완료" 신호인 ACK 메시지를 송신자에게 전송합니다. 만약 송신자가 ACK 메시지를 받지 못하면 데이터를 재전송합니다. ACK 메시지도 acknowledgement number을 통해 관리합니다. Acknowledgement number는 수신된 데이터의 바이트 수만큼 증가합니다. 예를 들어 1000 bytes의 데이터가 수신되면 acknowledgement number는 1000만큼 증가합니다. 

ACK를 받지 않은 데이터는 재전송할 가능성이 있기 때문에 송신자는 ACK를 받지 않은 데이터를 버퍼링 합니다. 

Flow control 

수신자는 자신이 처리할 수 있는 데이터의 양(receive window)을 송신자에게 알림으로써 flow control을 수행합니다. 송신자는 수신자의 receive window만큼 데이터를 전송합니다. 

Window 헤더에 receive window를 표시

Congestion control 

네트워크 정체를 방지하기 위한 기능으로 receive window와 달리 송신자가 단독으로 구현합니다. 관련 알고리즘에는 TCP Vegas, Westwood, BID, CUBIC이 있습니다. 

 

데이터 송수신 

TCP를 활용해 데이터를 전송하기 위해서는 다양한 레이어를 거쳐야 합니다. 크게는 user, kernel, device 영역으로 나눌 수 있습니다. User와 kernel 영역의 작업은 CPU가 수행하며 device 영역은 해당 device에서 작업을 수행합니다. 

송신 

https://d2.naver.com/helloworld/47667

Application에서 데이터를 송신할 때 어떻게 처리하는지 각 레이어별로 살펴보겠습니다. 

  • Application: 애플리케이션에서 전송할 데이터를 write 시스템 콜을 호출해서 다음 레이어로 전송합니다. Linux는 socket을 일종의 파일로 관리하기 때문에 데이터를 전송하고자 하는 소켓을 특정하기 위해서 file descriptor을 사용합니다. 
  • File: 단순 검사 후 파일 구조체에 연결된 소켓 구조체를 사용해서 소켓 함수를 호출합니다. 
  • Sockets: 소켓은 2개의 버퍼(receive socket buffer, send socket buffer)를 가지고 있습니다. Write 시스템 콜은 send socket buffer의 뒷부분에 추가(append)됩니다. 이는 데이터의 전송을 순서대로 하기 위함입니다. 
  • TCP: 데이터 전송을 위한 TCP segment를 생성합니다. 
  • IP: IP 패킷을 생성합니다(IP 헤더 추가) 
  • Ethernet: ARP(Address Resolution Protocol)을 활용해 next hop IP의 MAC 주소를 찾습니다. 그 후 ethernet 헤더를 패킷에 추가합니다. 
  • 드라이버: NIC 제조사가 정의한 "드라이버 - NIC" 통신 규약에 따라 패킷 전송을 요청합니다. 
  • NIC(Network Interface Card): 패킷 전송 요청을 받으면 메인 메모리에 있는 패킷을 자신의 메모리로 복사하고, 네트워크 선으로 전송합니다. 

수신 

https://d2.naver.com/helloworld/47667

데이터를 수신받을 때 어떻게 동작하는지 살펴보겠습니다. 

  • NIC(Network Interface Card): 패킷을 NIC의 메모리에 기록 후 호스트의 메모리 버퍼로 전송합니다. 호스트 메모리로 데이터가 전송되면 NIC가 호스트 운영체제에 인터럽트를 발생시킵니다. 
  • 드라이버: 자신이 처리할 수 있는 패킷인지 검사 후 패킷 상위 레이어로 패킷을 전달합니다. 
  • Ethernet: Ethernet 헤더를 제거 후 IP 레이어로 데이터를 전달합니다. 
  • IP: 호스트가 처리해야 하는 패킷이면 TCP 레이어로 데이터를 전달합니다. 만약 호스트가 처리할 데이터가 아니라면(IP routing) 데이터를 다른 장비로 전송합니다. 
  • TCP, Sockets: 해당 패킷과 관련된 connection을 찾습니다. 패킷의 <source IP, source port, target IP, target port>를 식별자로 사용합니다. 패킷은 receive socket buffer에 추가됩니다. 
  • File, Application: 애플리케이션에서 read 시스템 콜을 호출하면 socket buffer에 있는 데이터를 user 영역의 메모리로 복사합니다. 복사된 데이터는 receive socket buffer에서 제거됩니다. 

 

ETC 

TCP와 관련된 흔한 오해를 풀고자 아래와 같은 질문에 대답해 보도록 하겠습니다. 

클라이언트의 커넥션 생성 요청에 서버는 새로운 포트를 할당하는가? 

서버는 클라이언트의 TCP 커넥션 생성 요청 시 새로운 포트를 할당하지 않습니다. 하지만 새로운 file descriptor을 생성합니다. 아래 사진에서는 8080 포트에서 실행 중인 서버에 nc 커맨드를 사용해 커넥션을 맺은 후 lsof 커맨드를 통해 file descriptor 정보를 확인한 결과를 나타내고 있습니다. 

Client connection

  • 서버는 8080 포트에서 클라이언트의 연결 요청을 수신(LISTEN) 
  • 클라이언트와 연결을 맺으면 별도의 file descriptor(위 사진에서는 FD 칼럼의 85u, 3u)를 생성 
  • 서버는 클라이언트와의 연결을 기존 8080 포트를 사용해서 맺음 
  • 클라이언트는 서버와 연결을 맺기 위해서 ephemeral 포트(54744)를 사용 

서버는 최대 포트 개수만큼만 클라이언트와 커넥션을 맺을 수 있는가? 

서버는 클라이언트와 커넥션을 맺을 때 새로운 포트를 할당하지 않습니다. 따라서 서버가 연결을 맺을 수 있는 클라이언트의 수는 포트의 수와 무관합니다(단, 클라이언트가 서버와 연결을 맺을 때 새로운 포트를 할당받기 때문에 한 대의 노드에서 사용 가능한 포트의 수 이상의 커넥션을 외부와 맺는 것은 불가능합니다). 

서버가 맺을 수 있는 최대 연결의 수는 프로세스의 최대 open file descriptor의 수와 메모리 등의 리소스에 의해 결정됩니다. 

 

Reference 

Naver D2

RFC 793

728x90

'Operating System' 카테고리의 다른 글

[OS] sendfile 시스템 콜과 kafka zero-copy  (0) 2023.08.24
복사했습니다!