【问题标题】:C++ server cannot read my message from python client via socketC++ 服务器无法通过套接字从 python 客户端读取我的消息
【发布时间】:2015-06-02 16:29:30
【问题描述】:

我写了一个 python 客户端脚本通过 tcp 向服务器发送消息。

import socket

TCP_IP = '127.0.0.1'
TCP_PORT = 12003
BUFFER_SIZE = 1024
MESSAGE = b"Hello, World!"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()

print "received data:", data

服务器可以接收我的数据,但似乎无法读取数据。日志信息复制如下。

I0328 21:45:24.493249   505 prset04.cpp:210] reading the message (3472609771221168177 bytes)
E0328 21:45:25.493088   505 prset04.cpp:162] unable to receive on socket
I0328 21:45:25.493285   505 prset04.cpp:215] echoing the message
E0328 21:45:25.493479   505 prset04.cpp:185] unable to send on socket

我认为 C++ 套接字模块和 python 之间可能存在一些不同。但是我不知道那里出了什么问题,因为我不熟悉 C++ 和套接字。

任何想法或解释都会非常有帮助!

谢谢

服务器代码:

static void OnClient(const int sk) {
    size_t len;
    char buf[1024];

    // Read the message length.
    if (!ReadBytes(sk, reinterpret_cast<char*>(&len), sizeof(len))) {
        LOG(ERROR) << "unable to read message length";
        return;
    }

    LOG(INFO) << "reading the message (" << len << " bytes" << ")";

    // Read the message.
    ReadBytes(sk, buf, len);

    LOG(INFO) << "echoing the message";

    // Echo the message.
    WriteBytes(sk, buf, len);
}

static bool ReadBytes(const int sk, char* buf, const size_t n) {
    char* ptr = buf;
    while (ptr < buf + n) {
        if (!SetReadTimeout(sk)) {
            return false;
        }

        auto ret = recv(sk, ptr, ptr - buf + n, 0);
        if (ret <= 0) {
            LOG(ERROR) << "unable to receive on socket";
            return false;
        }

        ptr += ret;
    }

    return true;
}

【问题讨论】:

  • 我不知道Python 是如何工作的,但我怀疑它在发送消息之前将长度作为二进制整数发送。也许应该是len = ReadBytes(sk, buf, sizeof(buf));?另外我认为您可能在recv() 中计算错误的缓冲区。应该是recv(sk, ptr, n - (ptr - buf), 0);
  • @Galik 提供了 C++ 代码,应该没有问题。它不能被修改,否则我宁愿写一个 python server.anyway thx!
  • 你的 C++ ReadBytes 函数的 Python 等价物在哪里?!看来你忘了用 Python 实现协议了。

标签: python c++ sockets boost tcp


【解决方案1】:

就像 Galik 已经说过的那样,Python 不会像您的程序所期望的那样在字符串之前发送字符串的长度。而 C/C++ 也不这样做。

如果您希望您的 Python 程序与您的 C 程序一起工作,您必须考虑以下几点:

  1. 使用struct 模块将字符串打包成所需的长度
  2. 打包字符串时使用网络字节顺序
  3. 您应该知道size_t 之类的声明取决于体系结构,并且在 64 位和 32 位体系结构之间有所不同。如果您希望它们在架构之间兼容,您可以使用固定大小的整数,例如 uint32_t

示例代码:

from struct import pack
message = "Hello World"
data = pack('!i%ds' % len(message), len(message), message))

如果您无法更改 C 代码以使用网络字节顺序,您的具体代码应如下所示:

from struct import pack
message = "Hello World"
data = pack('<Q%ds' % len(message), len(message), message))

&lt; = 使用小端字节序

Q = 使用无符号 64 位整数(sizet_t 在 64 位架构上)

【讨论】:

  • 感谢您的解释。我试过你的例子,很接近。我得到了以下信息>>收到的数据:o,World!�o��0......我想我需要将'i'格式更改为其他人,因为它是64位架构。我试过'd''q''f',他们都失败了。我没有在 python 文档中找到 8 字节长的整数格式。那么我该如何解决呢?非常感谢!
  • 它不起作用,因为 C 代码没有使用网络字节顺序。我已经用一个适合你的代码示例编辑了我的答案。
  • 哇,效果很好。太感谢了。我应该学习一些有关网络字节顺序的知识。
【解决方案2】:

正如 Galik 指出的那样,您的 python 脚本不会发送任何长度的消息。虽然您的 c++ 服务器读取 4 个字节(如果您使用 64 位 linux,则为 8 个字节)并期望它们是消息的长度。 所以前 4 个字节是“地狱”,二进制形式将是服务器尝试读取的大量字节。

要解决此问题 - 在您的 python 脚本中发送前 4 个字节作为消息长度。 此外,您还需要使用网络字节顺序(如果您打算坚持使用二进制)来确保正确读取字节。 使用 ntohl() 函数将网络字节序号转换为主机字节序号。

【讨论】:

    猜你喜欢
    • 2017-03-12
    • 2017-09-19
    • 1970-01-01
    • 1970-01-01
    • 2017-04-30
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    相关资源
    最近更新 更多