Search code examples
pythonc++socketstcp

data sent and received through tcp socket not the same


My data sent and received through a tcp connection doesn't match up.

I have a raspberry hosting a tcp server written in c++. This is used only by my python module using python's socket module. I send a string to which the server responds with with an unsigned short integer. What I send and receive seem to be completely different. Some examples:

| sent in hex | received as string |
| ----------- | ------------------ |
| 0xb6fc      |  b'\x0b\xaa'       | 
| 0x80f5      |  b'\xb6h'          |
| 0xf93b      |  b'X\xec           |
| 0x3167      |  b'\x95\x1b'       |

The only consistent factor is the size. There are always 2 bytes send and 2 bytes received. I tried using struct.unpack on the received data and got a completely different value.

source code

this is running on the server

unsigned short value = 0;

std::thread count_thr(counter, &toggle, &value);

while (1){
            memset(buf, 0, sizeof(buf));
            received = recv(new_fd, &buf, sizeof buf, 0);
            printf("received string: %s\n", buf);

            if (strcmp(buf, "exit") == 0){
                    printf("closing server...\n");
                    close(new_fd);
                    exit(0);
            }
            else if (strcmp(buf, "get") == 0){
                    int bytes_sent = send(new_fd, &value, sizeof value, 0);
                    printf("sending value: %x\nbytes sent: %i\n", value, bytes_sent);
            }
    }

and this on the client

try:
sock.sendall('get'.encode())
    data = sock.recv(32)
    length = len(data)
    print('data received: %s\nlength: %i' % (data, len(data)))
except OSError as error:
    msg = str(error)

Solution

  • As you just discovered, this is a self-inflicted race condition. The fix is easy: just take a local copy of value that will not be changed by the external thread before sending:

    unsigned short copy = value;
    int bytes_sent = send(new_fd, &copy, sizeof copy, 0);
    printf("sending value: %x\nbytes sent: %i\n", copy, bytes_sent);