我使用网络上另一台计算机上的winsock接收值。它是一个TCP套接字,消息的4个第一个字节带有其大小。服务器使用protobuf(来自谷歌的协议缓冲区)格式化消息的其余部分。
我认为问题在于服务器发送的值似乎是以char形式发送的十六进制值(即只有10个接收到0x10)。要接收这些值,我这样做:
bytesreceived = recv(sock, buffer, msg_size, 0);
for (int i=0;i<bytesreceived;i++)
{
data_s << hex << buffer[i];
}
其中data_s是一个字符串流。我可以使用protobuf中的ParseFromIstream(&amp; data_s)方法并恢复我想要的信息。
我遇到的问题是这非常非常长(我使用QSock的另一个实现,我不能用于我的项目,但速度要快得多,所以在服务器端没有问题。)
我尝试了很多东西,我从这里和互联网上的任何地方(使用字节数组,字符串),但没有任何作用。
我还有其他选择吗?
感谢您的时间和意见;)
答案 0 :(得分:2)
不确定这是否有用,但我之前使用过类似的协议(前4个字节保存一个长度为int的字节,其余是使用protobuf编码)并解码它我做了类似的事情(可能由于附加到字符串而不是最有效的解决方案):
// Once I've got the first 4 bytes, cast it to an int:
int msgLen = ntohl(*reinterpret_cast<const int*>(buffer));
// Check I've got enough bytes for the message, if I have then
// just parse the buffer directly
MyProtobufObj obj;
if( bytesreceived >= msgLen+4 )
{
obj.ParseFromArray(buffer+4,msgLen);
}
else
{
// just keep appending buffer to an STL string until I have
// msgLen+4 bytes and then do
// obj.ParseFromString(myStlString)
}
答案 1 :(得分:0)
我不会使用流操作符。它们用于格式化数据,而这不是您想要的。
您可以使用char类型(字节向量)保持std :: vector中接收的值。这基本上只是一个动态数组。如果要继续使用字符串流,可以使用带有缓冲区和长度的stringstream :: write函数。您应该从调用recv。
中获得缓冲区和字节数如果要使用vector方法,可以使用std :: copy使其更容易。
#include <algorithm>
#include <iterator>
#include <vector>
char buf[256];
std::vector<char> bytes;
size_t n = recv(sock, buf, 256, 0);
std::copy(buf, buf + n, std::back_inserter(bytes));
答案 2 :(得分:0)
你的问题有点含糊不清。让我们按照你的例子。您收到10
个字符,并希望将其作为十六进制数字检索。
假设recv
会给你这个字符串,你可以这样做。
首先使其终止:
bytesreceived[msg_size] = '\0';
然后您可以使用标准* scanf函数轻松读取此缓冲区中的值:
int hexValue;
sscanf(bytesreceived, "%x", &hexValue);
你去吧!
编辑:如果您以相反的顺序收到号码(01
10
),那么最好的方法就是手动转换它:
int hexValue = 0;
int positionValue = 1;
for (int i = 0; i < msg_size; ++i)
{
int digit = 0;
if (bytesreceived[i] >= '0' && bytesreceived[i] <= '9')
digit = bytesreceived[i]-'0';
else if (bytesreceived[i] >= 'a' && bytesreceived[i] <= 'f')
digit = bytesreceived[i]-'a';
else if (bytesreceived[i] >= 'A' && bytesreceived[i] <= 'F')
digit = bytesreceived[i]-'A';
else // Some kind of error!
return error;
hexValue += digit*positionValue;
positionValue *= 16;
}
这只是一个明显的例子。实际上,你可以通过比特移位来实现,而不是相乘。
答案 3 :(得分:0)
好的,黑暗中的一击:假设您的入口流是"71F4E81DA..."
,并且您想将其转换为字节流{ 0x71, 0xF4, 0xE8, ...}
。然后我们可以如下所示组装字符文字中的字节,如下:
char * p = getCurrentPointer();
while (chars_left() >= 2)
{
unsigned char b;
b = get_byte_value(*p++) << 8;
b += get_byte_value(*p++);
output_stream.insert(b);
}
这里我们使用一个小辅助函数:
unsigned char get_byte_value(char c)
{
if ('0' <= c && c <= '9') return c - '0';
if ('A' <= c && c <= 'F') return 10 + c - 'A';
if ('a' <= c && c <= 'f') return 10 + c - 'a';
return 0; // error
}
答案 4 :(得分:0)
哪种数据类型为buffer
?
整个事情看起来像一个伟大的大型无操作,因为operator<<(stringstream&, char)
忽略了基本说明符。 hex
说明符仅影响非字符整数类型的格式。确定你不想将文本数据交给protobuf。
只需将buffer
指针移交给protobuf,就完成了。