C++插座.常量字符* 正确到达,string.c_str() doenst

C++ Sockets. const char* arrives correctly, string.c_str() doenst

本文关键字:string str doenst 字符 常量 插座 C++      更新时间:2023-10-16

我正在处理一个C++套接字分配,我正在尝试将字符串从服务器发送到客户端。

const char* msg;
msg = "test";

导致我的客户端test打印到控制台,但是当我尝试以下操作时:

std::string msg;
std::getline(std::cin, msg);

打印的结果是胡言乱语。在发送之前,我序列化了一个保存消息并且消息完好无损的结构。当我检查反序列化的包时,消息搞砸了。

我使用以下结构:

struct Package{
unsigned int package_type;
const char* msg;
int senderid;
int receiveid;
void SerializeData(char* _data){
    memcpy(_data, this, sizeof(Package));
}
void DeserializeData(char* _data){
    memcpy(this, _data, sizeof(Package));
}
};

知道为什么代码中定义的常量字符*有效,而string.c_str()不起作用吗?

您的SerializeDataDeserializeData函数实际上根本不序列化/反序列化字符串。 它们序列化/反序列化指向char的指针,这是完全不同的。 这只是一个指针!

通过网络在不同进程之间传递实际指针很少有意义,因为每个进程都有自己的专用地址空间。

您的示例可能适用于"test" "test"因为它是在可执行文件本身中分配的编译时常量。 如果同一个可执行文件充当发送方和接收方,则常量字符串在两者上将位于同一位置是完全合理的。 (但是,不能保证。 操作系统强化功能(如地址空间布局随机化)将打破这种情况。 相比之下,string.c_str()提供的指针是非常短暂的,并且在运行时动态生成。

您需要将字符串实际序列化到数据包中。 这可能需要在某处添加一个长度字段,或者一些其他方法来处理可变大小的消息。

如果你的任务是只将字符串从一端发送到另一端,那么你可能会大大简化这个问题。 如果需要对任意消息进行完全序列化,则会变得更加复杂。 您要么需要围绕消息的某种语法,要么需要发送方和接收方之间对消息格式的某种共享期望。

在任何情况下,使用指针或引用

序列化结构时,都需要确保拉入指向或引用的对象,而不是直接拉入指针或引用。 完全通用的序列化并不容易。 正如@Sorin页面上其他地方所指出的,Google协议缓冲区是执行此操作的一种方法。

序列化包包含类似 0 0xabc 0 0 的内容,其中 0xabc 是内存中存储字符串的指针。它在另一边不匹配。

在十六进制编辑器或类似编辑器中转储序列化包,看看它是否有任何意义。您可能需要逐个序列化每个元素,并将实际字符串复制到序列化包中。

这很难做到。使用一些库为您进行序列化。这是一个 https://code.google.com/p/protobuf/但还有其他的。