2009-10-24 2 views
5

상당히 높은 업데이트 속도로 유선을 통해 C 구조체를 보내야합니다 (UDP 소켓과 XDR을 사용하여). 여분의 불필요한 트래픽을 몇 khz.소켓을 통한 전송을 위해 C/C++ 구조체를 델타 인코딩하는 방법

이것은 구조체의 데이터 중 일부가 변경되지 않았기 때문에 이전 C 구조체에 대해 현재 C 구조체를 델타 인코딩하는 것이 좋은 아이디어처럼 보일 것이라고 생각하기 때문에 " diff ".

그러나 궁금한 점은 데이터 무결성을 유지하는 이상적인 휴대용 방식에 이상적입니다. 단순히 데이터를 배타적 논리합으로 처리 할 수 ​​있습니까?

마찬가지로 접근법이 확장 성이 있어야 새로운 필드를 구조체에 추가하거나 필요에 따라 재정렬 할 수 있으므로 (패딩) 버전 정보를 필요로하는 것처럼 들리도록하는 것이 중요합니다.

모든 아이디어 또는 포인터 (기존 라이브러리가 있습니까?) 매우 높이 평가 될 것입니다!

감사

편집 : 그 사실에없는 주요 문제이기 때문에 모든 사람에 대한 답변을 제공 한 덕분에, 세부 사항의 수준은 정말 감사합니다, 내가, 내가 아마하지만 UDP를 언급하지 말았어야 실현, 앞서 언급 한 어려움을 설명하는 UDP 위에 구현 된 해당 프로토콜이 이미 있기 때문에 질문은 실제로 struct를 델타 인코딩 할 수있는 실현 가능한 수단에 대한 것이고 전송 메커니즘으로 UDP를 사용하는 것은 아닙니다. . 델타 인코딩하는

+0

나는 그것이 얼마나 많이 의존 생각을 Repurposes 압축 된 형식으로 CORBA 또는 프로토콜 버퍼와 같은 RPC

사용 DTLS를 사용하여 데이터가 변경 될 것입니다 (1 %? 10 %? 50 %?). 그리고 변경 사항은 얼마나 규칙적입니까? (동일 장소 또는 어디에서나 있습니까?) –

+0

그냥 궁금 해서요. XMLRPC, SOAP 또는 다른 통신 DBUS와 같은 unication 메커니즘? 구조체가 다른쪽에 도착하면 어떻게 될까요? – aneccodeal

답변

4

UDP는 주어진 패킷이 실제로 수신되었음을 보장하지 않으므로 "지난 시간과의 차이"로 전송 한 내용의 인코딩은 문제가 있습니다. 을 알 수 없습니다. "마지막 시간"이었습니다. 본질적으로 어떤 패킷을 받았는지 확인하기 위해 UDP 위에 약간의 오버 헤드를 만들어야합니다. (각 패킷에 고유 한 ID로 태그를 붙입니다.) -이 경로를 찾으려는 모든 사람은 자신을 더 자주 찾거나 UDP 기반의 TCP 스트리밍 인프라 스트럭처 복제의 어려움이 거의 없습니다. 단단하고 잘 발달되지는 않았습니다. (분명히 때때로 평범한 제품보다 약간의 이점을 얻기 위해 페이로드의 특별한 특성을 활용할 수도 있습니다. 이전 TCP).

송신이 단방향 송신기에서 수신인이어야합니까? 이러한 경우 (즉, 수신자가 승인 또는 재전송을 보내면 안됨) 이러한 라인을 따라 할 수있는 일은별로 없습니다. 한가지 생각할 사항 : 수신자가 잠시 동안 동기화되지 않는 것이 좋다면, 송신자는 두 종류의 패킷을 보낼 수 있습니다 - 하나는 구조체의 현재 값의 전체 그림과 함께, 고유 한 태그가 적어도 매 5 분마다 전송되어야합니다 (수신기가 이러한 "큰 패킷"중 두 개를 놓치면 수신기가 최대 15 분 동안 동기화되지 않을 수 있습니다). 빅 패킷이 고유 태그를 식별하고 (예 : 언급 한) XOR의 런 렝쓰로 인코딩 된 버전을 포함하여 마지막 "빅 패킷"의 업데이트 (차이)가있는 패킷

물론 run-length-encoded 버전을 준비하고 나면 서버는 크기와 전체 구조체의 크기를 비교하고 절약량이 많은 경우 델타 종류의 패킷 만 보냅니다. 필요한 것보다 조금 더 빨리 빅 패킷을 보내십시오 (신뢰성 향상). 수신자는 수신 한 마지막 빅 패킷 고유 태그를 추적하고 이에 속하는 델타 만 적용합니다 (클라이언트를 얼마나 정교하게 만들 었는지에 따라 누락 된 패킷 및 패킷이 누락되는 것을 방지합니다).

구조체의 C 레이아웃이 어떻게 정규적으로 통신해야하는지에 대해 서로 다른 아이디어를 가진 발신자와 수신자가 정확히 무엇을 의미하는지에 따라 버전을 & c해야 할 필요가 있습니다. 두 버전 모두에게 알려진 버전에 대한 핸드 셰이크 방법은 무엇입니까? 등), 합병증의 전체 우주를 추가 할 것입니다,하지만 그건 정말 또 다른 질문이며, 제목에 요약 된 핵심 질문은 이미 충분히 큽니다 ;-).

수신자로부터 보낸 발신자에게 다시 보내는 메타 메시지를 보낼 수있는 경우 (재생 또는 재발송 요청) 재생중인 다양한 숫자 매개 변수에 따라 다양한 전략을 디자인 할 수 있습니다. 나는 멍청이들이 꽤 자주해야 할 것 같아서, 큰 패킷 (구체적으로 식별 된 것 또는 "가장 신선하다")을 재송신하라는 요청은 옵션 공간을 추려내는 최고의 메타 전략이 될 수있다. (그렇지 않으면 폭발 할 위험이 있습니다 ;-). 그렇다면 발신자는 수신자가 큰 패킷 재전송을 요청하기 위해 사용하는 모든 전략을 모르게 알고있을 수 있으며 보낸 사람을 재배포하지 않고도 다양한 전략으로 수신자 측에서 실험 할 수 있습니다.

패킷 크기, 송신 빈도, 송신자가 송신자와 동기화되지 않는 시간을 허용 할 수있는 시간 등 모든 수치 매개 변수에 대한 구장 번호와 같은 세부 사항이 없으면 훨씬 많은 도움을 제공하기가 어렵습니다. 수신기, 네트워크 매개 변수 번들 등.하지만이 다소 일반적인 분석과 제안이 여전히 도움이되기를 바랍니다.

3

:

1)을 주기적으로 (예를 들어, 일단 제 "키 프레임")을 보낸다. 키 프레임은 델타가 아닌 전체 사본이므로 어떠한 이유로 든 통신을 잃어 버리면 다시 "신호 받기"를하기 전에 소량의 데이터 만 잃게됩니다. 간단한 패킷 헤더를 사용하면 패킷의 시작을 감지하고 패킷에 포함 된 데이터 유형을 알 수 있습니다.

2) 이전 패킷의 델타를 계산하고이를 압축 된 형식으로 인코딩합니다. 전송할 데이터의 유형과 일반적으로 변경되는 방식을 검토하면 매우 컴팩트 한 델타를 고안 할 수 있습니다. 그러나 델타의 크기를 확인해야 할 수도 있습니다 - 어떤 경우에는 효율적인 인코딩이 아닐 수도 있습니다 - 키 프레임보다 크면 대신 다른 키 프레임을 보낼 수 있습니다. 델타가 손실 또는 손실 여부를 결정할 수도 있습니다.

3) CRC 체크를 패킷에 추가하십시오 (CRC32 검색). 이렇게하면 수신자가 패킷이 손상되지 않았 음을 확인하여 잘못된 패킷을 건너 뛸 수 있습니다.

참고 :

  • 는 UDP를 통해이 일에주의 - 그것은 당신의 패킷이 당신이 그들을 보낸 같은 순서로 도착 보장을 제공하지 않습니다. 분명 델타는 패킷이 순서대로 작동하는 경우에만 작동합니다. 이 경우 순서가 잘못된 수신을 감지 할 수 있도록 각 패킷에 일련의 양식을 추가해야합니다 (첫 번째 패킷은 "1"이고 두 번째 패킷은 "2"등). 디코딩 할 때 올바른 순서로 재조합 할 수 있도록 수신기에 "n"패킷 버퍼를 유지해야 할 수도 있습니다 (물론 이것은 약간의 대기 시간을 초래할 수 있습니다). UDP를 통해 일부 패킷을 잃어 버리는 경우도 있는데,이 경우 다음 키 프레임까지 기다려야 신호를 다시받을 수 있습니다. 따라서 키 프레임이 치명적인 정전을 피할 수있을만큼 자주 있어야합니다 당신의 통신에서.

  • 압축 사용 (zip 등)을 고려하십시오. 전체 패킷을 우편으로 친숙한 방식으로 만들 수 있습니다 (예 : 유사한 값 (특히 0)을 함께 묶을 가능성이있는 바이트를 그룹화하여 데이터를 다시 정렬) 한 다음 비 압축 델타보다 작게 압축합니다. 당신은 델타의 모든 노력에 전혀 갈 필요가 없을 것입니다 (그리고 당신은 패킷 주문 등에 대해 걱정할 필요가 없을 것입니다).

편집 - 새로운 필드를 추가하거나 미래에 델타 인코딩을 변경할 수 있도록 항상 패킷의 버전 번호 (또는 패킷 형)를 사용! 어쨌든 키/델타 프레임을 차별화하려면이 기능이 필요합니다.

+0

첫 번째 쪽지가 "reinvent TCP"로 더 간결하게 작성되지 않았습니까? –

+0

추가하기 만하면이 세부 수준으로 들어가 줘서 고마워, 정말 고맙습니다. – guest

+0

@guest - 걱정할 필요가 없습니다. 그것이 당신이 찾고 있던 해결책을 제공하지 않았더라도 그것이 계몽 적이거나 재미 있었기를 바란다. –

1

본질적으로 신뢰할 수없고 순서가 맞지 않는 UDP의 델타 인코딩 값이 특히 쉽게 될 것이라고 확신하지 않습니다. 대신 변경된 필드의 ID와 현재 값을 보냅니다. 또한 전송하려는 데이터 구조에 추가 필드를 추가하려는 경우 변경 사항이 필요하지 않습니다. 이 작업을 수행하는 표준 방법을 원한다면 SNMP를 살펴보십시오. 당신이 들여 놓을 수있는 것일 수도 있고, 너를 위해 약간 헐렁 할 수도있다. (이것은 필드 이름을 세계적으로 한정하고 ASN.1을 사용한다. 둘 다 최대의 상호 운용성을 제공하지만 패킷의 일부 바이트를 희생시킨다.)

0

압축 옵션

사용

기존 헤더 압축 라이브러리

관련 문제