Проблемы с анализом протокола TLV на основе TCP в C ++ - PullRequest
0 голосов
/ 31 октября 2011

Я пытаюсь реализовать протокол (T) LV через TCP, отправляя буферы протокола от клиента Python и получая его с сервера C ++.

Мой код выглядит примерно так:

char* buffer[RCVBUFSIZE];
int recvsize= 0;
// Filling my buffer with as much as possible.
while(true) {
  if(recvsize == RCVBUFSIZE) {
    break;
  } else if(recvsize+= recv(sock, buffer+recvsize, sizeof(buffer)-recvsize, 0) < 1) {
    break;
  }
}
//Parsing LV protocol
while(true) {
  unsigned short protosize= 0;
  //Copy first two bytes into protosize
  memcpy((char *) &protosize, buffer, sizeof(unsigned short));
  if(protosize == 0) { break; } // Protocol indicates EOM be setting length to "0"
  void* protomsg[protosize];
  memcpy(protomsg, buffer+sizeof(unsigned short), protosize);
  int msglength= sizeof(unsigned short)+protosize;
  //Now I'll move the whole buffer to the left so that I don't have to keep track of where I'm at.
  memmove(buffer, buffer+msglength, RCVBUFSIZE-msglength);
  protoMsg pm;
  if(!pm.ParseFromArray(protomsg, protosize)) { break; } // Parsing failed.
  // Do stuff with parsed message.
}

Теперь у меня есть несколько проблем:

  • Цикл while, получающий сообщение, никогда не прекращается.Я подозреваю, что вызов recv блокируется, когда больше не осталось никаких данных, в то время как я ожидал, что они вернутся с ошибкой.Я нашел функцию выбора, чтобы проверить, есть ли что прочитать.Я попробую.Но когда я вызываю функцию receive только один раз, чтобы пропустить эту проблему (полученное сообщение имеет размер ~ 10 байт, поэтому я ожидаю, что все будет собрано за один вызов.) У меня возникает другая проблема:
  • memcpy и memmove don 'Кажется, что работает как ожидалось.В первом цикле короткое замыкание обрабатывается, как и ожидалось (я получаю то же значение, которое отправляю на другой стороне), но затем все из анализа буфера протокола завершается неудачно.Я что-то не так понял?

Редактировать: Что касается комментария о ntohs - я передаю short как little-endian в настоящее время, забыл упомянуть об этом.(Я изменит это все еще, кстати.)

Третье редактирование: Код теперь работает, но мне пришлось изменить следующее:

char* buffer[RCVBUFSIZE];
int recvsize= 0;
// Filling my buffer with as much as possible.
while(true) {
  if(recvsize == RCVBUFSIZE) {
    break;
  } else if((recvsize+= recv(sock, buffer+recvsize, sizeof(buffer)-recvsize, 0)) < 1) {
    break;
  } else if(recvsize > 1) {
    unsigned short msglength= 0;
    memcpy((char *) &msglength, buffer+recvsize-sizeof(unsigned short), sizeof(unsigned short));
    if(msglength == 0) { break; } // Received a full transmission.
  }
}

Итак, сначала яМне нужно было добавить квадратные скобки вокруг оператора recvsize+= recv(), а во-вторых, поскольку неблокирующий метод не работал по какой-то причине, я сейчас проверяю, переводятся ли последние два переданных байта в 0 при чтении короткого знака без знака.Это, вероятно, приводит к проблеме, если я случайно прочитал 0, а не поле длины.Я начну еще один вопрос по этому поводу, вероятно.

Я также изменил protomsg на char[], но я не думаю, что это действительно что-то изменило.(У меня уже был разбор, работающий с массивом void ..)

1 Ответ

1 голос
/ 31 октября 2011

Если полученное вами сообщение всегда имеет размер около 10 байтов, а RCVBUFSIZE больше этого значения, вы никогда не прекратите работу, пока не возникнет ошибка чтения данных.Кроме того, переменная buffer в вашем коде является массивом RCVBUFSIZE указателей, вероятно, не того, что вы хотите.

Измените код следующим образом:

#define MINIMALMESSAGESIZE 10  // Or what the size may be
char buffer[RCVBUFSIZE];
int totalrecvsize= 0;
int recvsize= 0;
while(true) {
  if(totalrecvsize >= MINIMALMESSAGESIZE) {
    break;
  } else if(recvsize= recv(sock, buffer+totalrecvsize, sizeof(buffer)-totalrecvsize, 0) < 1) {
    break;
  } else {
    totalrecvsize += recvsize;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...