Ошибка при получении из сокета

Мне нужно получать сообщения с сервера, и я могу сделать это до сих пор, но у меня все еще есть проблема, я не знаю, что это такое. Текст определяет, что сообщение имеет следующий формат:

  • как заголовок, 2 байта для размера остальной части сообщения (полезная нагрузка +
    контрольная сумма);
  • в качестве трейлера, 1 байт для контрольной суммы (контрольная сумма
    рассчитывается включая 2 байта размера)
  • , а остальное
    байты для самой полезной нагрузки (в середине сообщения)

Я пытался получить это сообщение, и поэтому я использовал функцию получения, что это ниже

/**
Receive data from the connected host
*/
string client::receive(int size){
//string buffer;
string reply;
std::vector<char> buffer(size, 0);
//strcpy(buffer, "\0");
// memset(&buffer[0], 0, sizeof(buffer));
int result = recv(sock, buffer.data(), buffer.size(), 0);

if( result < 0){
puts("recv failed");
}
cout << "read bytes: " << result << endl;
cout << "buffer: " << buffer.data() << endl;
//reply = stringToBit(buffer);
reply = buffer.data();
cout << "reply: " << reply << endl;

return reply;
}

но проблема в том, что, когда я помещаю прием в какое-то время, чтобы получать все сообщения, все начинает становиться странным. Сначала я понял, что мне нужно только очистить буфер, но все остается странным, потому что для сообщений информация, которую я получаю:

1-е сообщение: НОЛЬ — Количество полученных байтов: 2

2-е сообщение: пользователь принят — количество полученных байтов: 14

3-е сообщение: 5 — Количество полученных байтов: 1

4-е сообщение: НОЛЬ — Количество полученных байтов: 2

5-е сообщение: unprintable_char501&х, мкр-LDT = ‘т <1t? 1-t $; =: — Количество полученных байтов: 30

6-е сообщение: НОЛЬ — Количество полученных байтов: 1

.

.

.

5-е сообщение всегда меняется, но остальные (сообщения и количество байтов) всегда одинаковы. Глядя на сообщения 1 из 3, я подумал, что, возможно, 3 — это заголовок с размером, 2 — это сообщение, а 3 — контрольная сумма. Но, получив все эти НОЛЬ вместо любой полезной информации, заставляет меня думать иначе.

Кто-то имеет представление о том, что может происходить? У меня нулевой контроль над сервером, я могу только поверить, что сервер отправляет эти сообщения, как указано.

0

Решение

Сервер отправляет вам размер сообщения. Вы должны использовать это в ваших интересах. Кроме того, способ определения вашей функции затрудняет сообщение об ошибках. Вы должны рассмотреть что-то вроде этого:

// receives a fixed number of bytes. returns zero or a negative number on error
int client::receiveBytes(size_t n, void* buffer)
{
char* p = reinterpret_cast<char*>(buffer);
while (n)
{
int got = recv(sock, p, n, 0);
if (got <= 0)
return got;
n -= got;
p += got;
}
return 1;
}

/**
Receive data from the connected host
*/
int client::receive(std::string& reply)
{
reply.clear();
uint16_t replyLength = 0;    // or the appropriate 16-bit type if your compiler doesn't provide <cstdint>

int result = receiveBytes(2, &replyLength);
if (result <= 0)
return result;

if (replyLength == 0)  // <-- you could add more length validation here
return -1;          // <-- or whatever error code you wish...

reply.resize(replyLength);
result = receiveBytes(replyLength, &reply[0]);

if (result <= 0)
return result;

// verify the checksum.  failure indicates we have lost sync...

// I'm assuming here that the checksum is computed using plain char's,
const char* p = reinterpret_cast<const char*>(&replyLength);
char chksum = *(p++) + *p;

for (size_t i = 0; i < replyLength - 1; ++i)
chksum += reply[i];

if (chksum != reply[replyLength - 1])
{
// there is not much that can be done to recover sync with this protocol
// the best option the caller has is to close the connection and start anew.
reply.clear();
return -1;   // or whatever error code you wish...
}
reply.resize(replyLength - 1);
return reply.size();
}
1

Другие решения

Я создал другую функцию приема только для 16-битных целых чисел и (по какой-то причине я не знаю), я понял, что байты были обменены. Например:

Я получил число 3840, что двоичное представление: 0000111100000000

Но я должен был получить 15, что двоичное представление:
0000000000001111

Итак, в дополнение к приему, я добавляю идею обмена байтами

 int client::receiveSize(){
int16_t size;
int result = recv(sock, &size, sizeof(size), 0);

int hibyte = (size & 0xff00) >> 8;
int lobyte = (size & 0xff);
size = lobyte << 8 | hibyte;
cout << "received: " << size << " and " << result<< endl;
return size;
}

Я понял (кстати! Я кое-что узнал), что я должен поместить именно тот тип данных, который я буду получать в recv. В противном случае я могу получить информацию, которая не имеет смысла.

-1

По вопросам рекламы [email protected]