我有一个非常奇怪的错误。
我有两个通过 TCP/IP 进行通信的应用程序。
应用程序 A 是服务器,应用程序 B 是客户端。
应用程序 A 每 100 毫秒向应用程序 B 发送一堆浮点值。
错误如下:有时应用程序 B 接收到的某些浮点值与应用程序 A 传输的值不同。
最初,我认为以太网或 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 加州 26 BF
即浮点赋值可能使值标准化,产生与原始值不同的值。
欢迎对此提出任何意见。
编辑2:
谢谢大家的回复。问题似乎在于交换的浮点数在通过“return”语句返回时被推入 CPU 的浮点堆栈。然后调用者从堆栈中弹出值,该值被四舍五入,但它是交换的浮点数,因此四舍五入会弄乱值。