[英]How to convert a string in cpp struct to python struct
我写了一个tcp服务器和tcp客户端,我想从客户端向服务器发送一个结构,然后服务器将结构发送回来。 服务器用cpp编写,客户端用python编写。 然后我遇到了一个问题,我的结构有一个类型是字符串的成员,然后我找不到合适的格式字符串来描述这个成员在 python( https://docs.python.org/2/library/struct.html ) . 所以我想知道如何在python中描述字符串属性?
以下是最少的代码:------server---------
#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,则大部分时间似乎都可以工作)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.