TCP / IP float transmission and data corruption

I have a very strange error.

I have two applications that communicate over TCP / IP.

Appendix A is the server, and Appendix B is the client.

Application A sends a bunch of float values ​​to application B every 100 milliseconds.

The error is this: sometimes some of the float values ​​received by application B do not match the values ​​passed by application A.

Initially, I thought the problem was with the Ethernet or TCP / IP drivers (something like data corruption). Then I tested the code on other Windows machines, but the problem persists.

Then I tested the code on Linux (Ubuntu 10.04.1 LTS) and the problem is still there !!!

Values ​​are recorded immediately before they are sent and immediately after they are received.

The code is pretty simple: the message protocol has a 4-byte header like this:

//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;
}

When I get the message "orientation", sometimes the value "azimuth" is different from the value specified by the server!

Shouldn't the data be the same all the time? Does TCP / IP guarantee data delivery without distortion? maybe an exception in the mathematical coprocessor affects the TCP / IP stack? The problem is that I get a small number of bytes first (4 bytes) and then the body of the message?

EDIT:

The problem is the endianess substitution procedure. The following code folds the continent of a specific float around, and then swaps it again and prints the bytes:

#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;
}

Conclusion:

7F 8A 26 BF 7F CA 26 BF

those. assigning a float probably normalizes the value, creating a different value from the original.

Any input is welcome.

EDIT2:

. , , swapped float, return, CPU. , , swapped float, .

+3
2

, , , , A, B.

, . , ntohs , - , , .

msg.length = htons(sizeof(ORIENTATION_MESSAGE) - sizeof(MESSAGE_HEADER));

, ...

0

TCP , , , , . , , XDR Google protobuf.

+3

Source: https://habr.com/ru/post/1765669/


All Articles