如何使用 QTcpSocket 获取 Protobuf 发送的数据 [重复]
Posted
技术标签:
【中文标题】如何使用 QTcpSocket 获取 Protobuf 发送的数据 [重复]【英文标题】:How to get datas send by Protobuf with a QTcpSocket [duplicate] 【发布时间】:2019-07-31 07:54:27 【问题描述】:我是 protobuf 和 QTcpServer/Socket
的新手,我想读取我的客户端发送的 .proto
数据,但是当我读取数据时,QString
done 是空的
现在,我只想在我的客户端连接时发送一条说“你好”的消息。 QTcpSocket::readAll
返回的QByteArray
不为空,但使用字节创建的QString
为空。
这是我的.proto
超基本的一个:
syntax = "proto3";
package protobuf;
message Message
string content = 2;
编写函数:
// When i'm connecting to the server i create a PlayerManager and i call this function with message = "hello"
void Server::sendMessageToPlayer(const PlayerManager& playerManager, const QString& message)
auto messageProto = new protobuf::Message;
messageProto->set_content(message.toStdString());
playerManager.socketManager()->sendData(*messageProto);
// I serialize the protobuf
template <typename protobufType>
void sendData(const protobufType& protobuf)
std::string dataToSend;
if (!protobuf.SerializeToString(&dataToSend))
// This never pass -> the protobuf is well serialize
qDebug() << "The protobuf send cannot be serialized, please, make sure that you used protobufs correctly";
// Before i write it
write(dataToSend);
void SocketManager::write(const std::string& data)
// I tried this but it's not working either
// QTextCodec* codec = QTextCodec::codecForName("CP1251");
// QString codecData = codec->toUnicode(data.c_str());
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_10);
out << data.c_str();
_tcpSocket->write(block);
qDebug() << block;
读取函数:
void SocketManager::read()
QByteArray bytes = _tcpSocket->readAll();
qDebug() << bytes;
// Doesn't work either
// QTextCodec* codec = QTextCodec::codecForName("CP1251");
// QString data = codec->toUnicode(bytes);
QString data(bytes);
qDebug() << data;
emitMessageType(data.toStdString());
void SocketManager::emitMessageType(const std::string& data)
// Protobufs can parse an empty string (and so, emit signal), to avoid that, the function will tell you if data
// are empty, then return
if (data.empty())
qDebug() << "Datas are empty";
return;
protobuf::Message message;
if (message.ParseFromString(data))
emit messageProtoReceived(message);
return;
qDebug() << "The data send cannot be translate, please, make sure that you used protobufs correctly";
所以,我希望我的客户在连接时收到“hello”,但我的调试是:
服务器端:
"\x00\x00\x00\b\x12\x05hello\x00"
客户端
"\x00\x00\x00\b\x12\x05hello\x00"
""
Datas are empty
当我使用QTextCodec
(代码的注释行)时,调试是:
服务器端:
"\x00\x00\x00\x0E\x00\x12\x00\x05\x00h\x00""e\x00l\x00l\x00o"
客户端
"\x00\x00\x00\x0E\x00\x12\x00\x05\x00h\x00""e\x00l\x00l\x00o"
"\u0000\u0000\u0000\u000E\u0000\u0012\u0000\u0005\u0000h\u0000e\u0000l\u0000l\u0000o"
The data send cannot be translate, please, make sure that you used protobufs correctly
所以QByteArea
被解析了,但是protobuf没有成功解析给定的字符串。
感谢您的阅读,希望您能帮助我
【问题讨论】:
out << data.c_str()
内部写入函数可能会首先丢弃\0
。尝试转换为QByteArray
,如下所述:***.com/questions/10767760/… 以确保通过套接字发送整个字符串。
QByteArray block(data.c_str(), data.length());
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_10);
_tcpSocket->write(block);
这是有效的!你能回答吗,我会把它标记为已接受
【参考方案1】:
不确定是否是这种情况,但文档说QString
的默认构造函数采用QByteArray
:
使用 fromUtf8() 将给定的字节数组转换为 Unicode。在第一个 0 字符处停止复制,否则复制整个字节数组。
因此,您可能在转换过程中遇到了一些麻烦。
作为替代方案,您可以尝试ParseFromArray
方法,而不是将QByteArray
转换为std::string
。
const auto byteArray = _tcpSocket->readAll();
protobuf::Message message;
if (!message.ParseFromArray(byteArray.data(), byteArray.size()))
qDebug() << "Failed to parse person.pb.";
【讨论】:
这是有效的,但只有当我按照@Zaiborg 告诉我的去做时。它也适用于 ParseFromString :)。不管怎么说,还是要谢谢你 !但我还有另一个问题,你似乎知道 protobuf。为了更清楚我的代码,我没有说我尝试在我的emitMessageType
函数中解析不同类型的.proto
。首先要解析的是 protobuf::Player,它要求一个 int AND 一个字符串。但是 protobuf::Player 使用 protobuf::Message 序列化的字符串成功解析,这很麻烦
抱歉@Ephesiel,但我不明白您的问题,也许您可以通过 protobuf 模型或代码本身的小示例在您的问题中提供更新。
抱歉,很难用一点评论来解释,这是我提出的另一个问题的链接-> link【参考方案2】:
out << data.c_str()
在SocketManager::write
中可能会首先丢弃\0
。尝试按照Correct way to losslessly convert to and from std::string and QByteArray 中的说明转换为QByteArray
,以确保发送整个字符串。
【讨论】:
以上是关于如何使用 QTcpSocket 获取 Protobuf 发送的数据 [重复]的主要内容,如果未能解决你的问题,请参考以下文章