TCP 및 UDP 패킷을 여러 조각으로 나눌 수 있습니까?


41

TCP 패킷이 조각으로 수신자에게 도착할 수 있습니까?

예를 들어, TCP 프로토콜을 사용하여 20 바이트를 보내는 경우 10 바이트가 아니라 10 바이트 정도가 아니라 한 번에 정확히 20 바이트를 수신한다고 100 % 확신 할 수 있습니까?

UDP 프로토콜에 대해서도 같은 질문입니다.
UDP를 신뢰할 수 없으며 패킷이 전혀 도착하지 않거나 다른 순서로 도착할 수는 없지만 단일 패킷은 어떻습니까? 도착하면 조각이 아닌 완전한 패킷인지 확인할 수 있습니까?


7
설명의 포인트 :이를 TCP 세그먼트 및 UDP 데이터 그램이라고합니다. 패킷이 아닙니다. TCP = 세그먼트, UDP = 데이터 그램, IP = 패킷, 이더넷 = 프레임, 다른 모든 계층 (AFAIK)에서는 PDU (프로토콜 데이터 단위)라고합니다.
joeqwerty

답변:


33

TCP 패킷이 조각으로 수신기에 도착할 수 있습니까?

예. TCP는 일반적으로 경로 MTU를 결정하고 성능상의 이유로 패킷을보다 작게 유지하려고하지만 IP는 조각화를 지원합니다. 조각화는 데이터 그램 손실률을 치명적으로 증가시킵니다. 경로의 패킷 손실률이 10 % 인 경우 데이터 그램을 두 개의 패킷으로 조각화하면 데이터 그램 손실률이 거의 20 %가됩니다. 패킷 중 하나라도 손실되면 데이터 그램이 손실됩니다.

그래도 걱정할 필요가 없으며 TCP 레이어도 걱정하지 않아도됩니다. IP 계층은 패킷을 전체 데이터 그램으로 재 조립합니다.

예 : TCP 프로토콜을 사용하여 20 바이트를 보내면 10 바이트가 아니라 다른 10 바이트 정도 한 번에 정확히 20 바이트를 수신 할 것이라고 100 % 확신 할 수 있습니까?

아니요, 그러나 그것은 패킷과 관련이 없습니다. TCP는 기본적으로 응용 프로그램 메시지 경계를 유지하지 않는 바이트 스트림 프로토콜입니다.

UDP 프로토콜에 대해서도 같은 질문입니다. UDP를 신뢰할 수없고 패킷이 전혀 도착하지 않거나 다른 순서로 도착할 수 없다는 것을 알고 있습니다.

TCP에서도 마찬가지입니다. 패킷은 패킷입니다. 차이점은 TCP에는 재시도 및 재주문이 프로토콜에 내장되어 있지만 UDP는 그렇지 않다는 것입니다.

그러나 1 패킷은 어떻습니까? 도착하면 조각이 아닌 완전한 패킷인지 확인할 수 있습니까?

아니요, 그러나 그것은 당신의 문제가 아닙니다. UDP 프로토콜은 데이터 그램 리 어셈블리를 처리합니다. 그것은 그 일의 일부입니다. (실제로 IP 프로토콜은 UDP 프로토콜에 대해이 작업을 수행하므로 UDP는 단순히 IP 위에 계층화하여 수행합니다.) 데이터 그램이 두 개의 패킷으로 분할되는 경우 IP 프로토콜은 UDP 프로토콜에 대해이를 재구성합니다. 완전한 데이터를 볼 수 있습니다.


10
초보자 독자에게는 마지막 비트를 명확하게 설명 할 가치가 있습니다 . 해당 데이터 그램에 대한 전체 데이터가 표시됩니다 . 분할 패킷 중 하나가 손실되면 데이터 그램이 손실되고 UDP 계층은이를 알 수 없습니다. 데이터 그램의 모든 패킷이 수신되는 한 IP 계층에서 패킷이 조립 된 다음 UDP 계층으로 전달됩니다. 이것은 데이터 스트림에서 "청크"가 누락 될 가능성을 배제하지 않습니다. pedant가 아니지만이 내용을 배우고있을 때 2 차 또는 3 차가 교과서를 통과 할 때까지 IP 조각과 UDP 손실의 차이점을 알지 못했습니다.
Justin ᚅᚔᚈᚄᚒᚔ

20

그들이 실제로 물리적으로 한 번에 도착하는지 확신 할 수 없습니다. TCP / UDP 아래의 데이터 링크 계층은 원하는 경우 패킷을 분할 할 수 있습니다. 특히 인터넷이나 제어 할 수없는 네트워크를 통해 데이터를 보내면이를 예측하기가 어렵습니다.

그러나 데이터가 수신기에서 하나의 패킷 또는 여러 패킷에 도착하더라도 상관 없습니다. OS는 이러한 패킷의 연결을 추상화해야하므로 응용 프로그램의 경우 모든 것이 한 번에 도착한 것처럼 보입니다. 따라서 커널 해커가 아닌 한 대부분의 경우이 데이터가 하나 이상의 패킷으로 전송되는지 걱정할 필요가 없습니다.

UDP의 경우 OS는 추상화를 수행하므로 데이터를 수신하는 응용 프로그램은 데이터가 전송 된 패킷 수를 알 필요가 없습니다. 그러나 TCP와의 차이점은 데이터가 실제로 도착한다는 보장이 없다는 것입니다. 데이터가 여러 패킷으로 분할 될 수 있으며 일부는 도착하지만 일부는 도착하지 않을 수 있습니다. 수신 응용 프로그램의 경우 완료 여부에 관계없이 데이터 스트림처럼 보입니다.


네트워크 카드 드라이버가 커널이 아닌 패킷을 다시 어셈블하지 않습니까?
bluehallu

2
@Hallucynogenyc : 변경 사항이없는 한, 인터넷 프로토콜은 576 바이트 이상의 패킷을 여행 중 언제라도 분할 할 수 있도록 설계되었지만 최종 수신자 외에는이를 다시 결합 할 것으로 기대하지 않습니다. 더 큰 패킷의 사용은 대부분의 경우 오버 헤드를 줄이기위한 노력이라고 생각합니다. 일단 패킷이 이동 중 어느 시점에서 분할되면 오버 헤드가 이미 발생하여 최종 수신자가 아무 도움이되지 않고 재분할해야 할 경우 손상 될 수 있습니다.
supercat

576 바이트를 초과하는 패킷은 분할 될 수 있지만 그 크기보다 작은 패킷은 분할되지 않을 수 있습니다. 분할 패킷을 처리 할 수없는 임베디드 시스템은 그보다 큰 것을 요구하지 않아야합니다.
supercat

1
@ mauro.stettler : "베어 메탈"(여러 네트워크 인터페이스 칩과 직접 통신하는 코드 작성)에 TCP 스택을 작성했습니다. 더 긴 패킷을 분할하기 위해 576 바이트 제한이있는 링크와 통신하는 하드웨어의 경우 간단합니다. 패킷 재 조립은 훨씬 더 복잡합니다. 특히 패킷을 완전히 수신하기 전에 여러 다른 패킷 조각을 수신 할 수 있기 때문입니다.
supercat

가에 대한 분할하지 않을 것을 희망이 작은 각각의 필요한 "보장 된 최대 크기"가 있기 때문에 페이로드 (약 10 또는 20 바이트가 확인을해야), 적어도 68 바이트 (포함 : IPv4의의 IP paquets, 양에 대한이 하위 수준 헤더를 계산하지 않는 IP 헤더). en.wikipedia.org/wiki/Maximum_transmission_unit 의 첫 번째 표를 참조하십시오 . HOSTS에 필요한 최소 크기의 576 바이트와 다릅니다 (즉, 모든 중간 홉이 아닌 전송의 시작 또는 끝). 그리고 신중하게 : 페이로드 는 여전히 낮습니다 (각 레이어의 헤더는 약간의 공간을 차지하므로).
Olivier Dulac

14

예. 연속 문자 블록은 send () 호출에 해당합니다.

TCP :

Send: AA BBBB CCC DDDDDD E         Recv: A ABB B BCC CDDD DDDE

전송 된 모든 데이터는 순서대로 수신되지만 반드시 동일한 청크 일 필요는 없습니다.

UDP :

Send: AA BBBB CCC DDDDDD E         Recv: CCC AA E

데이터의 순서가 반드시 같을 필요는 없으며 전혀 수신 할 필요는 없지만 메시지는 전체적으로 보존됩니다.


5

예 : TCP 프로토콜을 사용하여 20 바이트를 보내면 10 바이트가 아니라 다른 10 바이트 정도 한 번에 정확히 20 바이트를 수신 할 것이라고 100 % 확신 할 수 있습니까?

TCP는 스트림 프로토콜이며 데이터를 순서대로 유지하지만 메시지별로 그룹화하지는 않습니다. 반면에 UDP는 메시지 지향적이지만 신뢰할 수 없습니다. SCTP 는 두 가지 장점을 모두 갖추고 있지만 NAT가 인터넷을 차단하기 때문에 기본적으로 사용할 수 없습니다.


1

TCP 스트림의 맨 처음에 20 바이트를 보내면 두 개의 10 바이트 조각으로 도착하지 않을 것이라는 확신이 있습니다. 이는 TCP 스택이 이러한 작은 세그먼트를 보내지 않기 때문입니다. 최소 MTU 크기가 있습니다. 그러나, 센드가 스트림 중앙 어딘가에 있으면 모든 베팅이 해제됩니다. 프로토콜 스택은 세그먼트를 채우고 전송하기 위해 10 바이트의 데이터를 소비 한 다음 다음 10 바이트는 다른 세그먼트로 이동합니다.

프로토콜 스택은 데이터를 청크로 나누고 대기열에 넣습니다. 청크 크기는 경로 MTU를 기반으로합니다. 전송 작업을 수행하는데 여전히 대기중인 데이터가있는 경우 프로토콜 스택은 일반적으로 대기열의 끝에있는 세그먼트를 들여다보고 해당 세그먼트에 더 많은 데이터를 추가 할 공간이 있는지 확인합니다. 공간은 1 바이트만큼 작을 수 있으므로 2 바이트 전송도 2 개로 나눌 수 있습니다.

다른 한편으로, 데이터의 분할은 부분 판독이있을 수 있음을 의미합니다. 수신 작업은 하나의 세그먼트에 도착할 때 잠재적으로 깨어나 데이터를 얻을 수 있습니다. 광범위하게 구현 된 소켓 API에서 수신 호출은 20 바이트를 요청할 수 있지만 10으로 리턴 할 수 있습니다. 물론 20 바이트를 수신하거나 연결이 끊길 때까지 차단하는 버퍼링 계층을 작성할 수 있습니다. POSIX 세계에서이 API는 표준 I / O 스트림 일 수 있습니다 fdopen. 소켓 디스크립터가 FILE *스트림 을 확보 할 수 fread있으며이를 사용 하여 전체 요청이 read필요한만큼의 호출로 만족되도록 버퍼를 채울 수 있습니다 . .

UDP 데이터 그램은 데이터의 프레임을 구성합니다. 각 송신 호출은 데이터 그램을 생성합니다 (하지만 코킹에 대해서는 아래 참조). 다른 쪽은 전체 데이터 그램을받습니다 (그리고 소켓 API에서이를 보유 할만큼 큰 버퍼를 지정해야합니다. 그렇지 않으면 데이터 그램이 잘립니다). 큰 데이터 그램은 IP 조각화로 조각화되고 응용 프로그램에 투명하게 다시 어셈블됩니다. 조각이 없으면 전체 데이터 그램이 손실됩니다. 해당 상황에서 부분 데이터를 읽을 수있는 방법이 없습니다.

여러 작업에서 단일 데이터 그램을 지정할 수있는 인터페이스 확장이 있습니다. Linux에서 소켓은 "코르크"될 수 있습니다 (전송 금지). 데이터가 코르크 처리되는 동안 기록 된 데이터는 단일 장치로 조립됩니다. 그런 다음 소켓이 "확인되지 않은"경우 단일 데이터 그램을 보낼 수 있습니다.


이것은 거짓입니다 : 10 또는 20 바이트 페이로드로 paquet을 보내면 1 paquet이 생성되며 ipv4를 사용하는 경우 다른 프로토콜 계층의 모든 헤더를 추가 할 때도 위와 같이 paquet이 생성됩니다. 68 바이트 내에 들어가므로 1 패킷의 모든 홉을 통과합니다. TCP 스택은 (첫 번째 단락에서 암시 된 바와 같이) mtu가 채워질 때까지 기다리지 않습니다 (즉, 적절한 크기의 패킷을 만들기 위해 여러 패킷을 추가하십시오) ....이 동작은 많은 것을 깨뜨릴 것입니다. 이 "조각"이 동일한 호스트 쌍에서 전송 된 경우에도)
Olivier Dulac

@OlivierDulac : 맞지 않습니다. TCP는 보통 필요에 따라 패킷을 생성하여 네트워크 사용을 최적화하려고 시도하므로 Kaz에서 설명한대로 20 바이트가 두 개의 다른 패킷으로 끝날 수 있습니다. TCP_NODELAY 소켓 옵션을 사용하여 제어 할 수 있습니다.이 옵션은 응용 프로그램에서 더 빠른 TCP 네트워킹이 필요한 경우 바이트를 패킷으로 디스패치하는 Nagles 알고리즘을 비활성화합니다. 또한 68 바이트는 패킷 길이에 대한 사실상의 표준이 아닙니다. 1500 바이트가 더 일반적인 기본값입니다 (이는 실제로 네트워크마다 다릅니다).
jjmontes 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.