У меня очень странная ошибка.
У меня есть два приложения, которые взаимодействуют по TCP / IP.
Приложение A является сервером, а приложение B является клиентом.
Приложение A отправляет набор значений с плавающей запятой в приложение B каждые 100 миллисекунд.
Ошибка заключается вследующее: иногда некоторые значения с плавающей точкой, полученные приложением B, не совпадают со значениями, передаваемыми приложением A.
Первоначально я думал, что возникла проблема с драйверами Ethernet или TCP / IP (своего родаповреждение данных).Затем я проверил код на других машинах Windows, но проблема осталась.
Затем я проверил код на Linux (Ubuntu 10.04.1 LTS), и проблема все еще существует !!!
Значения регистрируются непосредственно перед отправкой и сразу после их получения.
Код довольно прост: протокол сообщения имеет 4-байтовый заголовок, подобный следующему:
//message header
struct MESSAGE_HEADER {
unsigned short type;
unsigned short length;
};
//orientation message
struct ORIENTATION_MESSAGE : MESSAGE_HEADER
{
float azimuth;
float elevation;
float speed_az;
float speed_elev;
};
//any message
struct MESSAGE : MESSAGE_HEADER {
char buffer[512];
};
//receive specific size of bytes from the socket
static int receive(SOCKET socket, void *buffer, size_t size) {
int r;
do {
r = recv(socket, (char *)buffer, size, 0);
if (r == 0 || r == SOCKET_ERROR) break;
buffer = (char *)buffer + r;
size -= r;
} while (size);
return r;
}
//send specific size of bytes to a socket
static int send(SOCKET socket, const void *buffer, size_t size) {
int r;
do {
r = send(socket, (const char *)buffer, size, 0);
if (r == 0 || r == SOCKET_ERROR) break;
buffer = (char *)buffer + r;
size -= r;
} while (size);
return r;
}
//get message from socket
static bool receive(SOCKET socket, MESSAGE &msg) {
int r = receive(socket, &msg, sizeof(MESSAGE_HEADER));
if (r == SOCKET_ERROR || r == 0) return false;
if (ntohs(msg.length) == 0) return true;
r = receive(socket, msg.buffer, ntohs(msg.length));
if (r == SOCKET_ERROR || r == 0) return false;
return true;
}
//send message
static bool send(SOCKET socket, const MESSAGE &msg) {
int r = send(socket, &msg, ntohs(msg.length) + sizeof(MESSAGE_HEADER));
if (r == SOCKET_ERROR || r == 0) return false;
return true;
}
Когда яПри получении сообщения «ориентация» иногда значение «азимута» отличается от значения, отправленного сервером!
Разве данные не должны быть одинаковыми все время?TCP / IP не гарантирует доставку данных без повреждений?Может ли быть так, что исключение в математическом сопроцессоре влияет на стек TCP / IP?проблема в том, что я сначала получаю небольшое количество байтов (4 байта), а затем тело сообщения?
РЕДАКТИРОВАТЬ:
Проблема заключается в процедуре замены порядка байтов.Следующий код меняет местами порядковый номер определенного числа с плавающей запятой, а затем меняет его снова и печатает байты:
#include <iostream>
using namespace std;
float ntohf(float f)
{
float r;
unsigned char *s = (unsigned char *)&f;
unsigned char *d = (unsigned char *)&r;
d[0] = s[3];
d[1] = s[2];
d[2] = s[1];
d[3] = s[0];
return r;
}
int main() {
unsigned long l = 3206974079;
float f1 = (float &)l;
float f2 = ntohf(ntohf(f1));
unsigned char *c1 = (unsigned char *)&f1;
unsigned char *c2 = (unsigned char *)&f2;
printf("%02X %02X %02X %02X\n", c1[0], c1[1], c1[2], c1[3]);
printf("%02X %02X %02X %02X\n", c2[0], c2[1], c2[2], c2[3]);
getchar();
return 0;
}
Вывод:
7F 8A 26 BF 7F CA 26 BF
Т.е. присвоение с плавающей точкой, вероятно, нормализует значение, производя значение, отличное от оригинала.
Любые входные данные для этого приветствуются.
EDIT2:
Спасибовы все за ваши ответы.Кажется, проблема в том, что подкачка с плавающей запятой, когда возвращается с помощью оператора return, помещается в стек с плавающей запятой ЦП.Затем вызывающая сторона извлекает значение из стека, значение округляется, но это перестановка с плавающей точкой, и, следовательно, округление портит значение.