【问题标题】:data sent and received through tcp socket not the same通过 tcp socket 发送和接收的数据不一样
【发布时间】:2020-06-23 14:52:46
【问题描述】:

我通过 tcp 连接发送和接收的数据不匹配。

我有一个树莓派托管一个用 C++ 编写的 tcp 服务器。这仅由使用 python 的 socket 模块的我的 python 模块使用。我发送一个字符串,服务器用一个无符号短整数响应该字符串。我发送和接收的似乎完全不同。一些例子:

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

唯一一致的因素是尺寸。总是有 2 个字节发送和 2 个字节接收。我尝试在接收到的数据上使用struct.unpack,得到了完全不同的值。

源代码

这是在服务器上运行

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

这个在客户端

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)

【问题讨论】:

  • count_thr 是做什么的?
  • 它启动一个单独的线程,该线程不断更改value。实际上可能是这样,因为它可能会在 send 尝试发送时更改 value

标签: python c++ sockets tcp


【解决方案1】:

正如您刚刚发现的,这是一种自我造成的竞争条件。 修复很简单:只需获取value 的本地副本,在发送之前不会被外部线程更改:

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);

【讨论】:

  • 我刚刚测试了这个,并没有解决问题。接收和发送的值仍然不匹配
  • 你能把value的类型改成std::atomic_ushort吗?这可以强制编译器实际执行一次读取并将结果存储到copy
  • 我已经删除了整个线程调用,只是在value 中存储了一个简单的ushort,这似乎有一些效果。首先,当我将 value 更改为始终为 6969 时,我收到了 b'9\x1b'。当我将value 设置为0xabcd 时,我收到了b'\xcd\xab。字节的顺序似乎不正确,但这不是问题。我不明白当字符串中没有 2 \x 时会发生什么。
  • 6969 = 0x1b39。 ASCII 9 = 0x39。在 Python 中使用 struct.pack("<H", 6969) 自行检查。然后将该值传递给bytes.hex 以获取391b
  • 好吧,这意味着我得到的数据可能是正确的,只是解码错误
【解决方案2】:

正如 Botje 所说,我有一个竞争条件,因为 value 的数据在发送时不断被更改。另一个问题是我收到的数据不清楚,但事实证明它是 ASCII 字符而不是字节的十六进制表示。

解决了,

decoded_val = struct.unpack('<H', data)[0]

这条线解决了我的问题。我添加了[0],因为 unpack 返回了一个元组,并且第一项包含正确的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多