Python 无法理解通过 Winsock 发送的 C++ 字符串

python can't make sense of c++ string sent over winsock

本文关键字:C++ 字符串 Winsock Python      更新时间:2023-10-16

目标:

我正在编写一个套接字服务器/客户端程序(c ++是服务器,python是客户端)来发送携带数据的xml字符串。我的目标是能够通过套接字从 Python 中的 c++ 接收 xml 消息。

方法

VS2013 专业版Python 2.7.2 via Vizard 4.1

1)套接字通信创建得很好,没有问题。我可以发送/接收东西

2)初始化通信后,C ++开始使用Cmarkup创建XML对象。

3) C++ 将 XML 对象转换为 std::字符串类型

4) C++ 通过流将 std::string 发送到 Python

问题:

python中从C++收到的"字符串"被解释为垃圾符号(不是想冒犯,有人可能对它们有强烈的感情,我不;)这看起来像您在打开二进制文件时在记事本中看到的符号。这并不奇怪,因为通过流发送的数据是二进制的。

我无法弄清楚的是,如何让Python理解流。

尝试修复失败:

1)确保VS2013项目使用Unicode字符

2)尝试将流转换为python字符串并将其解码为string.decode()

3) 尝试使用 Unicode()

4)还尝试使用binascii()方法来获得有用的,小的改进,但仍然不是我从c ++发送的相同字符

如果有人能对为什么会发生这种情况提供一些见解,我将不胜感激。我已经阅读了几个关于通过套接字发送数据方式的论坛,但编码和解码的这一方面对我来说仍然是垃圾邮件-鲭鱼-砂锅。

下面是创建 xml、转换为字符串,然后发送的服务器代码

        MCD_CSTR rootname("ROOT");//initializes name for root node
        MCD_CSTR Framename("FRAME");//creates name for child node
        CMarkup xml;//initializes xml object using Cmarkup method
        xml.AddElem(rootname);//create the root node
        xml.IntoElem();//move into it
        xml.AddElem(Framename, MyClient.GetFrameNumber().FrameNumber);//create child node with data from elsewhere, FrameNumber is an int
        CStringA strXML = xml.GetDoc();//convert the xml object to a string using Cmarkup method
        std::string test(strXML);//convert the CstringA to a std::string type
        std::cout << test << 'n';//verify that the xml as a string looks right
        std::cout << typeid(test).name() << 'n';//make sure it is the right type
        iSendResult = send(ClientSocket, (char *)&test, sizeof(test), 0);//send the string to the client

以下是在 Python 中接收 xml 字符串的代码:

while 1:
    data = s.recv(1024)#receive the stream with larger than required buffer
    print(data)#see what is in there
    if not data: break#if no data then stop listening for more

由于test是一个字符串,因此这不起作用:

iSendResult = send(ClientSocket, (char *)&test, sizeof(test), 0);//send the string

std::string不是字符数组。 它是一个对象,该行所做的只是将无意义的字节发送到套接字。 您希望发送数据,而不是对象。

iSendResult = send(ClientSocket, (char *)test.c_str(), test.length(), 0);//send the string

你不能只在 std::string 的位置写入内存并认为这是序列化。 根据C++库的实现方式,std::string 很可能是一个包含指向实际字符数据的指针的结构。 如果传输指针,不仅无法发送字符数据,而且指针值在程序的当前实例以外的任何其他上下文中都没有意义。

而是序列化字符串的重要内容。 发送长度,然后发送字符数据本身。 像这样的东西。

uint32_t len = test.length();
send(..., &len, sizeof(uint32_t), ...);
send(..., test.c_str(), len, ...);