2010-03-05 6 views
14

다양한 길이의 텍스트 데이터가 클라이언트와 서버간에주고받는 클라이언트/서버 응용 프로그램에서 보내는 패킷의 끝을 어떻게 표시해야합니까? 예를 들어, 서버가 클라이언트로부터 패킷 데이터를 수신 할 때 클라이언트 패킷이 완전히 수신되었다는 것을 서버가 어떻게 알 수 있습니까?TCP 패킷 끝을 어떻게 표시해야합니까?

서버에 데이터 이전에 수신 할 패킷의 전체 길이를 알려주거나 패킷 끝을 표시하는 것이 일반적입니까?

보낸 데이터 중 일부는 길이가 길지 만 수천 가지가 될 수 있습니다.

+2

TCP 패킷 내에서 걱정할 필요가없는 응용 프로그램 수준의 메시지라고 생각합니까? –

답변

23

TCP는 연속적인 데이터 스트림을 제공합니다. TCP는 이 패킷을 사용하여으로 구현되었지만 TCP의 전체적인 점은이를 숨기는 것입니다.

마치 그림을 그리려는 벽처럼 생각하면됩니다. 벽은 벽돌로 만들어진다. 벽돌은 모르타르와 함께 붙어 있으며 석고는 벽면이 매끄 럽도록 적용됩니다. 벽돌은 IP 패킷이고 TCP는 석고입니다.

이제 부드럽게 회 반전 된 TCP 터널을 얻었으므로 여기에 구조를 추가하고 싶습니다. 상자를 그리면 그림이 서로 떨어져있게됩니다. 이것은 당신이 원하는 것입니다 : 약간의 "관리"구조 (도면 주위의 상자)를 데이터에 추가하는 것입니다.

많은 프로토콜은 packet이라는 개념을 사용합니다.이 개념은 고정 형식 관리 헤더로 시작하는 일련의 데이터입니다. 헤더에는 패킷이 끝나는 위치를 결정할 수있는 충분한 정보가 들어 있습니다. 예를 들어 패킷 길이를 포함한다. HTTP는 데이터가 하나 또는 여러 개의 미니 패킷으로 분할되는 "청크 분할 전송 인코딩"을 사용하여 Content-Length 헤더 또는 HTTP/1.1을 사용하여이를 수행합니다. 각 패킷은 정확히 미니 패킷 길이 표시로 구성된 간단한 헤더로 구성됩니다 .

또 다른 방법은 "정상적인 데이터"에 나타날 수없는 특수 터미네이터 시퀀스를 만드는 것입니다. 데이터가 텍스트이면 종결 자로 0의 값을 사용할 수 있습니다.

또 다른 방법은자가 종단 데이터를 사용하는 것입니다. 이것은 요소의 끝 부분에 도달했는지 여부를 언제든지 알 수있는 방식으로 구조화 된 데이터입니다. 예를 들어, XML 데이터는 <foo>...</foo>과 같은 중첩 된 쌍의 마커로 구성됩니다. 끝 마커 (</foo>)에 도달하면 요소가 완료되었음을 알게됩니다.

3

패킷을 시작 부분에 길이 필드가 포함되도록 구조화하십시오.

1

HTTP에서 신호를 가져옵니다.

문자의 종료 자 시퀀스를 사용하거나 메시지 헤더 어딘가에 길이를 지정하거나 두 가지를 똑똑하게 조합하십시오.

HTTP와 동일 : 헤더가 CR-LF-CR-LF로 끝납니다. 헤더를 지나친 데이터가있는 경우 데이터 길이는 헤더 중 하나에 있습니다.

+1

데이터는 (우연히) 수신 파서를 혼란스럽게하는 종결 자 시퀀스를 포함 할 수 있기 때문에 임의의 데이터를 전송해야 할 때 까다로운 문제가됩니다. 일종의 이스케이프 코드 프로토콜을 구현함으로써이를 피할 수는 있지만, 그 시점에서 길이 필드를 먼저 보내는 것보다 일이 더 복잡하므로 먼저 길이 필드를 보내고 간단하게 유지할 수 있습니다. –

2

보낸 사람이 길이를 알고있는 경우 보낸 사람은 고정 된 크기 필드 앞에 길이를 제공하고 그 다음에 가변 크기 데이터를 제공해야합니다. 꼬리 마커 대 장점은 수신기가 예상 된 양의 데이터를 최적화 할 수 있다는 것이다. 올바른 크기의 버퍼를 할당하십시오. 예를 들어, TCP/IP 프로토콜을 통한 스토리지는 TCP/IP와 동일한 문제를 가지고 있습니다. 이 경우 머리글은 나중에 예상되는 데이터의 길이를 제공합니다.

도로를 지나면 "머리글"에 다른 비트를 넣을 수 있습니다. 자신 만의 Layer-5 프로토콜을 성장시킬 수있는 구조를 갖추었기 때문에 기쁠 것입니다.

1

특히 대담한 느낌이 들면 TCP 소켓 대신 SCTP 소켓을 사용할 수 있습니다.

1

처음에 길이를 인코딩하면 가비지에주의하십시오. 예를 들어, 길이에 4 바이너리 바이트를 사용하고 일부 외부 프로브가 HTTP 요청을 보내는 경우, 막대한 숫자로 끝나고 영원히 기다릴 것입니다 (프로그램을 크래쉬시킬 수있는 버퍼를 할당하는 것은 말할 것도 없습니다). 서로 다른 기능을 통해 길이를 두 번 보내고 비교합니다 (예 : ~ len 및 len xor 0x139AF321). 누군가가 적극적으로 프로그램을 중단시키려는 경우 최대 값을 설정해야합니다. 나쁜 길이가되면 연결을 닫습니다.

트래픽이 암호화 된 경우 HMAC를 초과합니다.

관련 문제