python 无法理解通过 winsock 发送的 C++ 字符串

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

目标:

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

方法

VS2013专业版 Python 2.7.2 通过 Vizard 4.1

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

2) 初始化通信后,c++ 开始使用 Cmarkup

创建 xml 对象

3) c++ 将 xml 对象转换为 std::string 类型

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

问题:

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

我想不通的是如何让 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, ...);