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, ...);
目标:
我正在写一个套接字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, ...);