Мне нужно получать сообщения с сервера, и я могу сделать это до сих пор, но у меня все еще есть проблема, я не знаю, что это такое. Текст определяет, что сообщение имеет следующий формат:
Я пытался получить это сообщение, и поэтому я использовал функцию получения, что это ниже
/**
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 — контрольная сумма. Но, получив все эти НОЛЬ вместо любой полезной информации, заставляет меня думать иначе.
Кто-то имеет представление о том, что может происходить? У меня нулевой контроль над сервером, я могу только поверить, что сервер отправляет эти сообщения, как указано.
Сервер отправляет вам размер сообщения. Вы должны использовать это в ваших интересах. Кроме того, способ определения вашей функции затрудняет сообщение об ошибках. Вы должны рассмотреть что-то вроде этого:
// 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();
}
Я создал другую функцию приема только для 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. В противном случае я могу получить информацию, которая не имеет смысла.