使用stringstream从TCP套接字读取
Use stringstream to read from TCP socket
我正在使用一个套接字库(我宁愿不使用它),其recv
操作与std::string
一起工作,但只是recv
套接字函数调用的包装器,所以很可能我只得到了我想要的消息的一部分。我的第一反应是进入一个循环,并将接收到的字符串附加到另一个字符串,直到得到所有内容,但这似乎效率低下。另一种可能是对字符数组执行相同的操作,但这似乎很混乱。(在添加到数组之前,我必须检查字符串的大小,如果它溢出,我需要将字符串存储在某个地方,直到数组再次为空…)
所以我在考虑使用stringstream。我使用TLV协议,因此我需要首先将两个字节提取到unsigned short中,然后从stringstream中获取一定数量的字节,然后再次循环,直到到达分隔符字段。
有更好的方法吗?我是否完全走错了方向?有什么最佳实践吗?到目前为止,我一直只看到直接使用套接字库与字符数组,所以我很好奇为什么使用' std::string ' '与stringstreams可能是一个坏主意。
编辑:回复下面的评论:这个库是我们内部使用的,它不是公共的(虽然它没有什么特别的,主要只是套接字库的包装器,以添加异常等)。
我应该提到我有一个直接使用套接字库的工作原型。
工作原理如下:
int lengthFieldSize = sizeof(unsigned short);
int endOfBuffer= 0;//Pointer to last valid position in buffer.
while(true) {
char buffer[RCVBUFSIZE];
while(true) {
int offset= endOfBuffer;
int rs= 0;
rs= recv(sock, buffer+offset, sizeof(buffer)-offset, 0);
endOfBuffer+= rs;
if(rs < 1) {
// Received nothing or error.
break;
} else if(endOfBuffer == RCVBUFSIZE) {
// Buffer full.
break;
} else if(rs > 0 && endOfBuffer > 1) {
unsigned short msglength= 0;
memcpy((char *) &msglength, buffer+endOfBuffer-lengthFieldSize, lengthFieldSize);
if(msglength == 0) {
break; // Received a full transmission.
}
}
}
unsigned int startOfData = 0;
unsigned short protosize= 0;
while(true) {
// Copy first two bytes into protosize (length field)
memcpy((char *) &protosize, buffer+startOfData, lengthFieldSize);
// Is the last length field the delimiter?
// Then reply and return. (We're done.)
// Otherwise: Is the next message not completely in the buffer?
// Then break. (Outer while will take us back to receiving)
if(protosize == 0) {
// Done receiving. Now send:
SendReplyMsg(sock, lengthFieldSize);
// Clean up.
close(sock);
return;
} else if((endOfBuffer-lengthFieldSize-startOfData) < protosize) {
memmove(buffer, buffer+startOfData, RCVBUFSIZE-startOfData);
//Adjust endOfBuffer:
endOfBuffer-=startOfData;
break;
}
startOfData+= lengthFieldSize;
gtControl::gtMsg gtMessage;
if(!gtMessage.ParseFromArray(buffer+startOfData, protosize)) {
cerr << "Failed to parse gtMessage." << endl;
close(sock);
return;
}
// Move position pointer forward by one message (length+pbuf)
startOfData+= protosize;
PrintGtMessage(>Message);
}
}
所以基本上我有一个大循环,它包含一个接收循环和一个解析循环。有一个字符数组来回传递,因为我不能确定是否收到了所有内容,直到我真正解析它。我试图复制这种行为使用"适当的"c++(即std::string)
我的第一反应是进入一个循环,并将接收到的字符串附加到另一个字符串,直到我得到所有内容,但这似乎效率低下。
字符串连接在技术上是平台相关的,但str1 + str2
可能需要一个动态分配和两个副本(来自str1
和str2
)。这有点慢,但比网络访问快得多!因此,我的第一个建议是,跟着你的第一直觉走,看看它是否既正确又足够快。
如果不够快,并且您的分析器显示多余的字符串副本是罪魁祸首,请考虑维护一个字符串列表(也许是std::vector<string*>
),并在最后将所有字符串连接在一起。这需要一些小心,但应该避免一堆冗余的字符串复制。
但绝对是配置文件第一!
- 套接字读取后,我在缓冲区中看到意外输入
- 将"uint8_t"(从套接字读取)隐式转换为"char"安全吗
- 不要从输入队列套接字读取数据
- 使用RAW套接字读取ICMP响应
- UDP 套接字读取最后一个传入字节
- CAN套接字读取帧较晚
- Java 套接字读取在第二次读取时返回奇怪字符
- 如何使用 recv 或 C++ 中的读取功能从 tcp 套接字读取大请求
- C++ 从末尾包含空字符的套接字读取字符串
- 是否可以在使用 Boost::asio 之前从套接字读取后执行async_handshake
- C++,在阻塞模式下从套接字读取所有可用字节的最佳方法
- 使用 QT 从套接字读取
- 如何检测我是否有要从套接字读取的内容?(c++)
- 为什么从套接字读取时 CAN 总线帧 ID 向后?
- 从套接字读取到缓冲区
- 从套接字读取和向套接字写入
- C 从套接字读取到std :: String
- JAVA:我无法从套接字读取文本,通过C++程序发送
- boost::asio 从套接字读取 n 个字节到 Streambuf
- 无法从TCP套接字读取