python - 如何将cpp结构中的字符串转换为python结构

标签 python c++ struct

我写了一个tcp server和tcp client,我想从client发送一个结构到server,然后server再发回这个structure。服务器用cpp写的,客户端用python写的。 然后我遇到了一个问题,我的结构有一个类型为字符串的成员,然后我找不到合适的格式字符串来在 python 中描述这个成员(https://docs.python.org/2/library/struct.html)。 所以我想知道如何在python中描述字符串属性?

下面是最简单的代码: ------服务器------------

#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <iostream>

struct Message
{
    int id;
    std::string text;
};

int main()  
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in my_addr;  
    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(11111);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    unsigned retry_times = 0;
    while(retry_times < 3)
    {
        if(bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr)) == 0)
        {
            break;
        }
        sleep(1000);
        ++retry_times;
    }
    listen(sockfd, 1);

    struct sockaddr_in client_addr;              
    socklen_t addr_len = sizeof(client_addr);        
    int connfd = accept(sockfd, (struct sockaddr*)&client_addr, &addr_len);

    while(true)  
    {
        Message msg;
        unsigned int len = recv(connfd, &msg, sizeof(msg), 0);
        if(len == 0)
        {
            break;
        }
        std::cout << msg.id << "--" << msg.text << std::endl;
        send(connfd, &msg, sizeof(msg), 0);
    }

    close(connfd);
    close(sockfd);
}

------------客户端------------

import socket
import struct

class TCPClient:
    def __init__(self):
        self.server_address = ('127.0.0.1', 11111)  
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect_ex(self.server_address)

    def send(self, msg):
        self.sock.send(msg)

    def recv(self):
        return self.sock.recv(512)

    def close(self):
        self.sock.close()

if __name__ == '__main__':
    client = TCPClient()
    fmt = 'is'         #### what format string will be better? this fmt is useless 
    msg = bytearray(512)
    struct.pack_into(fmt, msg, 0, 1, "Hello")
    client.send(msg)
    data = client.recv()
    print struct.unpack_from(fmt, data)
    client.close()

最佳答案

没有 Python 格式字符串可以解决这个问题。根本原因是您正在网络上发送 std::string 的字节。但是 std::string 通常包含指向实际内容的指针(和大小),这意味着您根本没有发送实际内容!

要修复它,您有两个主要选择——要么修改您的结构:

struct Message
{
    int32_t id; // use a fixed-size integer type
    char text [50]; // assumes you know the max length
};

或者更常规地,编写一个序列化例程:

void send_msg(int fd, const Message& msg)
{
    // XXX: you must check the return value of send()
    send(fd, &msg.id, sizeof(msg.id), 0);
    uint32_t text_size = msg.text.size();
    send(fd, &text_size, sizeof(text_size), 0);
    send(fd, &msg.text.data(), msg.text.size(), 0);
}

现在我们发送 ID(4 字节,Python 格式 i),text_size(4 字节,无符号,Python 格式 I),然后是文本(text_size 字节,Python 格式'{}s'.format(text_size))。在接收端可以分两步解压:先解压iI得到ID和text_size,再解压'{}s'.format(text_size)得到正文。

请注意,由于您使用的是 TCP,因此可以进行部分写入和读取。所以你需要处理这样一个事实,即你的发送者可能只发送了一半的消息,而你的接收者可能只收到了一半的消息。您当前的逻辑无法处理此问题(但如果 text_size 小于 500,则大多数情况下可能会正常工作)。

关于python - 如何将cpp结构中的字符串转换为python结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46422463/

相关文章:

python - 如何按 4 个时间段和键对数据帧进行分组

python - edX 供应问题 : get stuck at, 任务:[edxapp |将 edx-platform repo check out 到 {{edxapp_code_dir}}]

c - 双向链表逆向——打印出垃圾数据

c# - 如何从结构列表中有效地选择与给定模式匹配的所有值?

python - 解包函数返回到 pandas 数据框列

python - 从 GridFS Python Flask Mongodb 检索和显示图像

c++ - 用于 C++ (MFC) 的 SQLite OLE DB 驱动程序

c++ - 通用 Makefile 忽略变量

C++ 使用 .getline() 从文件中读取第一行

c - 如何复制指针以指向同一对象