C++进程间共享两串数据
Sharing two strings of data between processes in C++
我最近遇到了一个问题,我有两个独立的进程需要共享两个字符串。 (一个动态 IP 地址和一个密钥)我习惯于为此使用 ROS,我会用两个字符串定义一个 ROS 消息并将其从一个发送到另一个。
然而,我们正在努力使我们的应用程序尽可能简单,从而尽可能避免使用第三方软件。为此,我最初计划使用共享内存来发送一个包含两个 std::string
的结构,但后来才意识到这不是一个小问题,因为这个结构的大小是动态的...
我也考虑过使用套接字或队列等其他方式,但我总是 运行 遇到事先不知道该结构的大小的问题。如何解决这个问题?有没有一种方法可以做到这一点而不涉及定义一些协议,在该协议中您可以在字符串前面加上它的大小并以 null 或类似的方式结束它?
这是我的代码片段,它使用 Qt 创建一个 SharedMemory 来传递这个结构(当然不成功)。
struct
{
std::string ip_address;
std::string key;
}server_data_t;
#define SERVER_DATA_LEN sizeof(server_data_t)
class SharedMemoryManager : public QSharedMemory
{
...
QByteArray SharedMemoryManager::read()
{
QLOG_TRACE() << "SharedMemoryManager::read()";
QByteArray readData;
try
{
if(!isAttached())
throw std::runtime_error("Share memory segment has not been opened yet");
lock();
readData = QByteArray(static_cast<char *>(data()), size());
unlock();
return readData;
}
catch (std::exception &e)
{
QLOG_ERROR() << e.what();
return readData;
}
}
void SharedMemoryManager::write(const QByteArray &byte_array)
{
QLOG_TRACE() << "SharedMemoryManager::write()";
try
{
if(!isAttached())
throw std::runtime_error("Share memory segment has not been opened yet");
lock();
{
auto *from = byte_array.data();
char *to = static_cast<char*>(data());
memcpy(to, from, qMin(size(), byte_array.size()));
}
unlock();
}
catch (std::exception &e)
{
QLOG_ERROR() << e.what();
}
}
}
...
SharedMemoryManager _shm_manager;
server_data_t server_data;
server_data.ip_address = ...;
server_data.key = ...;
char *p = (char*)&server_data;
QByteArray byte_array = QByteArray(p, sizeof(server_data_t));
_shm_manager.write(byte_array);
...
SharedMemoryManager _shm_manager;
QByteArray byte_array = _shm_manager.read();
auto server_data = reinterpret_cast<server_data_t *>(byte_array.data());
std::cout << server_data->ip_address << std::endl;
当它尝试访问字符串时失败。
共享内存应该没问题(你甚至让 Qt 完成所有艰苦的工作)
您可能需要的是这样的东西,它在您的共享内存中具有固定大小并且仍然有足够 space 来容纳您的字符串。
const std::size_t message_buf_size = 256;
struct data_t
{
char message[message_buf_size]; // copy string into this and terminate with 0
std::uint8_t ipv4[4];
}
请注意,字符串的数据无论如何都会在堆上分配(除了经过优化的小字符串),而不是在共享内存中。
我最近遇到了一个问题,我有两个独立的进程需要共享两个字符串。 (一个动态 IP 地址和一个密钥)我习惯于为此使用 ROS,我会用两个字符串定义一个 ROS 消息并将其从一个发送到另一个。
然而,我们正在努力使我们的应用程序尽可能简单,从而尽可能避免使用第三方软件。为此,我最初计划使用共享内存来发送一个包含两个 std::string
的结构,但后来才意识到这不是一个小问题,因为这个结构的大小是动态的...
我也考虑过使用套接字或队列等其他方式,但我总是 运行 遇到事先不知道该结构的大小的问题。如何解决这个问题?有没有一种方法可以做到这一点而不涉及定义一些协议,在该协议中您可以在字符串前面加上它的大小并以 null 或类似的方式结束它?
这是我的代码片段,它使用 Qt 创建一个 SharedMemory 来传递这个结构(当然不成功)。
struct
{
std::string ip_address;
std::string key;
}server_data_t;
#define SERVER_DATA_LEN sizeof(server_data_t)
class SharedMemoryManager : public QSharedMemory
{
...
QByteArray SharedMemoryManager::read()
{
QLOG_TRACE() << "SharedMemoryManager::read()";
QByteArray readData;
try
{
if(!isAttached())
throw std::runtime_error("Share memory segment has not been opened yet");
lock();
readData = QByteArray(static_cast<char *>(data()), size());
unlock();
return readData;
}
catch (std::exception &e)
{
QLOG_ERROR() << e.what();
return readData;
}
}
void SharedMemoryManager::write(const QByteArray &byte_array)
{
QLOG_TRACE() << "SharedMemoryManager::write()";
try
{
if(!isAttached())
throw std::runtime_error("Share memory segment has not been opened yet");
lock();
{
auto *from = byte_array.data();
char *to = static_cast<char*>(data());
memcpy(to, from, qMin(size(), byte_array.size()));
}
unlock();
}
catch (std::exception &e)
{
QLOG_ERROR() << e.what();
}
}
}
...
SharedMemoryManager _shm_manager;
server_data_t server_data;
server_data.ip_address = ...;
server_data.key = ...;
char *p = (char*)&server_data;
QByteArray byte_array = QByteArray(p, sizeof(server_data_t));
_shm_manager.write(byte_array);
...
SharedMemoryManager _shm_manager;
QByteArray byte_array = _shm_manager.read();
auto server_data = reinterpret_cast<server_data_t *>(byte_array.data());
std::cout << server_data->ip_address << std::endl;
当它尝试访问字符串时失败。
共享内存应该没问题(你甚至让 Qt 完成所有艰苦的工作) 您可能需要的是这样的东西,它在您的共享内存中具有固定大小并且仍然有足够 space 来容纳您的字符串。
const std::size_t message_buf_size = 256;
struct data_t
{
char message[message_buf_size]; // copy string into this and terminate with 0
std::uint8_t ipv4[4];
}
请注意,字符串的数据无论如何都会在堆上分配(除了经过优化的小字符串),而不是在共享内存中。