【发布时间】:2011-10-08 22:58:20
【问题描述】:
我的 C++ 客户端/服务器应用程序有一个小问题。它使用 boost::asio 进行远程通信,使用协议缓冲区进行序列化。这里是客户:
// Time to write
char sizeMessage[20];
string content = request.SerializeAsString();
size_t request_length = content.size();
boost::asio::write(s, boost::asio::buffer(content.c_str(), request_length));
boost::system::error_code error;
boost::asio::read(s, boost::asio::buffer(sizeMessage, 20));
int bufferSize = atoi(sizeMessage);
char* responseString = new char[bufferSize];
size_t reply_length = boost::asio::read(s, boost::asio::buffer(responseString, bufferSize), boost::asio::transfer_all(), error);
if(!error){
response.ParseFromArray((const void*)responseString, reply_length);
success = true;
}else{
response.set_status(ExecResponse::ERROR);
}
delete[] responseString;
在我的应用程序的这个特定场景中,服务器响应的大小可能会有所不同,从几个字节到几 MB 不等。出于这个原因,服务器首先写入输出的大小,然后我用它来为我的缓冲区分配适量的内存。出于某种原因,我在读取数据时出现错误(始终正确读取大小)。一点调试发现 asio.misc:2 通过谷歌搜索我发现它是 EOF (实际上读取的字节数小于缓冲区大小)。这里是服务器端:
ExecResponse response;
ExecutionServerHandler execHandler(this->sharedData);
execHandler.process(rd, request, response);
string output = response.SerializeAsString();
//First write the length
ostringstream stringLength;
stringLength << output.size();
response.PrintDebugString();
string lengthString = stringLength.str();
size_t bw = ba::write(bsocket_, ba::buffer(lengthString));
bw = ba::write(bsocket_, ba::buffer(output));
这实际上是我第一次使用 boost,所以我不是一个经验丰富的开发人员。此外,值得一提的是,在我的应用程序的其他部分,这种机制有效,但我的其他消息有一些不同:虽然它们的大小仍然可变,但它们总是很小(几百字节)。服务器端是相同的,但在客户端我使用的是 boost::asio::transfer_at_least(1) 并且我没有提前写大小。如果我将这些更改应用于这种情况,我注意到 read 调用能够检索多达 65536 个字节并且不再检索(过早返回 EOF)。我的开发机器是 64 位的 Debian 5 和 Ubuntu 10.04,而 Boost 1.40 和 1.47 的行为相同。如果有人意识到我做错了什么,我会很感激指出。我迫不及待地想要让它发挥作用。
【问题讨论】:
-
我也不是 boost::asio 方面的专家,但是在服务器端写一个可变长度的字符串 (
lengthString) 并且总是在客户端读取 20 个字节对我来说看起来很可疑.每当lengthString小于20 字节时,您已经将部分有效负载读入sizeMessage,因此没有足够的字节来填充responseString。 -
您好,感谢您的评论。它给了我一个线索。我用服务器端的长度调整了字符串的大小,使其始终包含 20 个字符(用 \0 填充剩余空间),同时强制客户端全部使用。这解决了这个问题。我的假设是第二次调用 read 正在读取包含长度的字符串的剩余字符,因此我得到了一个过早的 EOF。非常感谢!
-
@reima 评论应该是一个答案
标签: c++ networking boost client-server boost-asio