문제

장치와 바이너리 데이터를 패킷(64바이트)으로 보내고 받고 있습니다.데이터에는 특정 형식이 있으며 그 중 일부는 요청/응답에 따라 다릅니다.

이제 수신된 데이터에 대한 해석기를 설계하고 있습니다.단순히 위치별로 데이터를 읽는 것은 괜찮지만, 다양한 응답 형식이 있을 때는 그다지 멋져 보이지 않습니다.현재 해당 목적을 위해 몇 가지 구조체를 만들려고 생각하고 있지만 패딩이 어떻게 될지는 모르겠습니다.

더 좋은 방법이 있을까요?


관련된:

도움이 되었습니까?

해결책

나는 이전에 이 작업을 수없이 수행했습니다.매우 일반적인 시나리오입니다.제가 거의 항상 하는 일이 많이 있습니다.

이를 가장 효율적으로 만드는 것에 대해 너무 걱정하지 마십시오.

패킷을 포장하고 푸는 데 많은 시간을 소비한다면 언제든지 더 효율적으로 변경할 수 있습니다.아직까지 구현해야 하는 경우는 없었지만 네트워크 라우터를 구현한 적은 없습니다!

구조체/공용체를 사용하는 것이 런타임 측면에서 가장 효율적인 접근 방식이지만 다음과 같은 여러 가지 문제가 있습니다.필요한 패킷의 옥텟 구조와 일치하도록 구조체/공용체를 압축하도록 컴파일러를 설득하고, 정렬 및 엔디안 문제와 디버그 빌드에서 온전성 검사를 수행할 기회가 없거나 거의 없기 때문에 안전성 부족을 방지하기 위해 노력합니다.

나는 종종 다음과 같은 것들을 포함하는 아키텍처로 마무리됩니다.

  • 패킷 기본 클래스입니다.모든 공통 데이터 필드에 액세스할 수 있지만 수정할 수는 없습니다.데이터가 압축된 형식으로 저장되지 않은 경우 압축된 패킷을 생성하는 가상 기능이 있습니다.
  • 공통 패킷 유형에서 파생된 특정 패킷 유형에 대한 다양한 프레젠테이션 클래스입니다.패킹 기능을 사용하는 경우 각 프레젠테이션 클래스는 이를 구현해야 합니다.
  • 프레젠테이션 클래스의 특정 유형에서 추론할 수 있는 모든 것(예:공통 데이터 필드의 패킷 유형 ID)는 초기화의 일부로 처리되며 그렇지 않으면 수정할 수 없습니다.
  • 각 프리젠테이션 클래스는 압축이 풀린 패킷으로 구성될 수 있으며, 해당 유형에 대해 패킷 데이터가 유효하지 않은 경우 정상적으로 실패합니다.그런 다음 편의를 위해 공장에서 포장할 수 있습니다.
  • 사용할 수 있는 RTTI가 없으면 패킷 ID를 사용하여 "가난한 사람의 RTTI"를 얻어 개체가 실제로 어떤 특정 프리젠테이션 클래스인지 확인할 수 있습니다.

이 모든 것에서 수정 가능한 각 필드가 올바른 값으로 설정되었는지 확인하는 것이 가능합니다(디버그 빌드의 경우에도).많은 작업처럼 보일 수 있지만 잘못된 형식의 패킷을 갖는 것은 매우 어렵습니다. 미리 압축된 패킷 내용은 디버거를 사용하여 눈으로 쉽게 확인할 수 있습니다(모두 일반 플랫폼 기본 형식 변수에 있으므로).

보다 효율적인 스토리지 체계를 구현해야 하는 경우 추가 성능 비용을 거의 추가하지 않고 이 추상화로 래핑할 수도 있습니다.

다른 팁

스트러크 및 노조를 사용해야합니다. 연결의 양쪽에 데이터가 올바르게 포장되어 있는지 확인해야하며 연결의 양쪽이 다른 상태로 실행될 가능성이있는 경우 양쪽 끝에서 네트워크 바이트 주문으로 번역 할 수 있습니다. endianess.

예로서:

#pragma pack(push)  /* push current alignment to stack */
#pragma pack(1)     /* set alignment to 1 byte boundary */
typedef struct {
    unsigned int    packetID;  // identifies packet in one direction
    unsigned int    data_length;
    char            receipt_flag;  // indicates to ack packet or keep sending packet till acked
    char            data[]; // this is typically ascii string data w/ \n terminated fields but could also be binary
} tPacketBuffer ;
#pragma pack(pop)   /* restore original alignment from stack */

그리고 할당 할 때 :

packetBuffer.packetID = htonl(123456);

그리고받을 때 :

packetBuffer.packetID = ntohl(packetBuffer.packetID);

다음은 몇 가지 토론입니다 엔지니어 그리고 정렬 및 구조 포장

구조를 포장하지 않으면 결국 단어 경계에 맞게 정렬되며 구조의 내부 레이아웃이 잘못되며 크기가 잘못됩니다.

데이터의 정확한 형식을 알지 못하고 최상의 솔루션이 무엇인지 말하기는 어렵습니다. 노조 사용을 고려해 보셨습니까?

나는 wuggy에 동의합니다. 코드 생성을 사용하여이를 수행 할 수도 있습니다. 간단한 데이터 정의 파일을 사용하여 모든 패킷 유형을 정의한 다음 Python 스크립트를 실행하여 프로토 타입 구조 및 각각의 직렬화/비 서식 기능을 생성하십시오.

이것은 "외부 박스"솔루션이지만 파이썬을 살펴 보는 것이 좋습니다. 건설하다 도서관.

Construct는 데이터 구조를 구문 분석하고 구축하기위한 파이썬 라이브러리입니다 (이진 또는 텍스트). 그것은 절차 코드보다는 데이터 구조를 선언적 방식으로 정의하는 개념을 기반으로합니다. 더 복잡한 구성은 더 간단한 계층의 계층으로 구성됩니다. 그것은 오늘날의 일반적인 두통 대신 파싱을 재미있게 만드는 첫 번째 도서관입니다.

Construct는 매우 강력하고 강력하며 튜토리얼을 읽으면 문제를 더 잘 이해하는 데 도움이됩니다. 저자는 또한 정의에서 자동 생성 C 코드를위한 계획을 가지고 있으므로 읽을 가치가 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top