2012-12-18 2 views
8

TCP를 통해 프로토콜 버퍼 메시지를 보내려고하지만 수신 측에서 '누락 필수 입력란'오류가 발생합니다. 분명히 모든 필드가 존재하더라도 구문 분석합니다. 메시지의 길이를 포함하는 메시지 앞에 4 바이트 헤더를 보냅니다.Google 프로토콜 버퍼 - 모든 입력란이 분명히 표시되어 있어도 필수 입력란이 누락되었습니다.

message ReplayRequest { 
    required string channel = 1; 
    required uint32 start = 2; 
    required uint32 end = 3; 
} 

클라이언트 측 내가 헤더를 인코딩 및 벡터에 메시지를 직렬화하고있어에서 : 여기

는 메시지 정의입니다.

ReplayRequest req; 
req.set_channel("channel") 
req.set_start(1); 
req.set_end(5); 
int byte_size = req.ByteSize(); 
std::vector<uint8_t> write_buffer(HEADER_SIZE + byte_size); 
encode_header(...); 
req.SerializeToArray(&write_buffer[HEADER_SIZE], byte_size); 

이것은 결과 버퍼의 16 진수이며, 처음 4 바이트는 인코딩 된 메시지 길이 (13 바이트)입니다. 서버 측

00 00 00 0d 0a 07 63 68 61 6e 6e 65 6c 10 01 18 05 

는 I 헤더를 수신하여 디코딩하고 N 헤더에보고 메시지 크기 N 바이트를 수신한다. 정확히 하나의 인코딩 된 클라이언트 측 마이너스 헤더와 동일한

0a 07 63 68 61 6e 6e 65 6c 10 01 18 05 

,하지만이 버퍼를 ParseFromArray하려고 할 때 오류 얻을 : 제거 헤더와 서버의 버퍼는

libprotobuf ERROR c:\umdf_runtime\protobuf-2.4.1\src\google\protobuf\message_lit 
e.cc:123] Can't parse message of type "ReplayRequest" because it is missing 
required fields: channel, start, end 

I 디코딩 실패 점이 protobuf이 부분에서 생성 한 코드에 눈치 디버깅하는 동안 :

bool ReplayRequest::IsInitialized() const { 
    if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false; 

    return true; 
} 

has_bits_가 서버 측에서 0으로 판독되고 웬일인지. 그러나 나는 이유를 해석 할 수 없다.

아이디어가 있으십니까?

중요한 경우 네트워크 부분에 boost :: asio를 사용하고 있습니다.

내가 parseFromArray를 호출하는 코드를 게시하도록하겠습니다 요청으로 업데이트

.

request_.ParseFromArray(&data_buffer_, data_buffer_.size()); 

request_는이 호출이 끝날 때까지 ReplayRequest 멤버 변수입니다.

data_buffer_는 TCP 데이터가 수신되는 <uint8_t>입니다.

올바르게 크기가 13 바이트로 확인되었으며이 16 진수 덤프는 직렬화 후에 버퍼 클라이언트 측을 덤프 할 때와 같은 결과입니다. 나는 클라이언트 측에서 ReplayRequest의 또 다른 인스턴스로 버퍼를 구문 분석 할 수 있어요 2

0a 07 63 68 61 6e 6e 65 6c 10 01 18 05 

업데이트, 즉 :

...snip... 
req.SerializeToArray(&write_buffer[HEADER_SIZE], byte_size); 
ReplayRequest test; 
test.ParseFromArray(&write_buffer[HEADER_SIZE], byte_size); 

테스트가 성공적으로 올바른 필드로 채워집니다.

+0

시도 서버에서 메시지가 잘못 표시되었습니다. ParseFromArray를 호출하는 코드를 게시 할 수 있습니까? –

+0

4 바이트 인코딩 된 메시지 크기 헤더가 빅 엔디안 인 것 같습니다 ... 수신자 측에서 빅 엔디안으로 정확하게 디코딩하고 있습니까? 올바른 N을 얻을 수 있기 때문에 올바르게 디코딩해야합니다. –

+0

@James 헤더가 올바르게 디코딩되었으므로 인쇄 된 서버 버퍼가 인코딩 된대로 정확히 13 바이트임을 확인할 수 있습니다. – indiosmo

답변

5

문제는 벡터에 대한 포인터가 아니라 벡터에 대한 포인터를 전달한다는 것입니다. 서버가 필요한 모든 필드 *, 그때 난 당신이 추출하고 분석하는 경우 궁금하네요 *이없는 것을 말한다면

대신
request_.ParseFromArray(&data_buffer_, data_buffer_.size());


request_.ParseFromArray(&data_buffer_[0], data_buffer_.size());

+0

그게 전부입니다. 이전에 서버의 단일 버퍼로 수신되었으므로 & data_buffer_ [HEADER_SIZE]이 (가) 정상적으로 작동합니다. 버퍼를 분리 한 후 접근자를 제거했습니다. 고맙습니다. – indiosmo

+0

np, 도와 주셔서 감사합니다 :) – g19fanatic

관련 문제