BOOST 阻塞、超时设置问题

heavyd 2020-06-11 12:03:46
麻烦各位!
系统:Ubuntu 16.0.4, BOOST
先说问题:
1、设置为非阻塞,socket.connect(...)应该如何设置超时?物理断网情况下,这里超时设置的不起作用;
2、第一boost::asio::read_until(...)超时可以正常获取并处理,但是第二个和以后的read_until(...)非阻塞就读不到数据了,要设置成阻塞才能读取数据。我想问一下,这种情况下,我需要设置超时,后面的read_until(...)应该如何设置超时?
代码如下:
int HttpCommandInterface::httpGet(const std::string request_path, std::string &header, std::string &content)
{
header = "";
content = "";
using boost::asio::ip::tcp;
try
{
boost::asio::io_service io_service;

// Lookup endpoint
tcp::resolver resolver(io_service);
tcp::resolver::query query(http_host_, std::to_string(http_port_));
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;

// Create socket
tcp::socket socket(io_service);
boost::system::error_code error = boost::asio::error::host_not_found;

fd_set fdSelect;
struct timeval tvSocket;
boost::asio::socket_base::non_blocking_io io_option(true);
// Iterate over endpoints and etablish connection
while (error && endpoint_iterator != end)
{
socket.close();
tvSocket.tv_sec = 10;
tvSocket.tv_usec = 0;
socket.open(tcp::v4());

setsockopt(socket.native(), SOL_SOCKET, SO_RCVTIMEO, &tvSocket, sizeof(tvSocket));
setsockopt(socket.native(), SOL_SOCKET, SO_SNDTIMEO, &tvSocket, sizeof(tvSocket));
io_option.set(true);
socket.io_control(io_option); //全部设为不阻塞 用select来检测

socket.connect(*endpoint_iterator++, error);

FD_ZERO(&fdSelect);
FD_SET(socket.native(), &fdSelect);
tvSocket.tv_sec = 10;
tvSocket.tv_usec = 0;
if (select(socket.native() + 1, NULL, &fdSelect, NULL, &tvSocket) <= 0 || !FD_ISSET(socket.native(), &fdSelect))
{
error = boost::asio::error::host_not_found;
}
else
{
error = boost::system::errc::make_error_code(boost::system::errc::success);
break;
}
}

if (error)
throw boost::system::system_error(error);

// Prepare request
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "GET " << request_path << " HTTP/1.0\r\n\r\n";

boost::asio::write(socket, request);
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
tvSocket.tv_sec = 10;
tvSocket.tv_usec = 0;

FD_ZERO(&fdSelect);
FD_SET(socket.native(), &fdSelect);
tvSocket.tv_sec = 10;
tvSocket.tv_usec = 0;
if (select(socket.native() + 1, &fdSelect, NULL, NULL, &tvSocket) <= 0 || !FD_ISSET(socket.native(), &fdSelect))
{
MYLOG_PRINT(wayToPrint, "RevTimeOut");
return 0;
}


boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");

io_option.set(false); //到这里 再ifdown也不会读也不会一直阻塞 必须要恢复阻塞 否则读不了数据
socket.io_control(io_option);

// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
MYLOG_PRINT(wayToPrint, "Invalid response");
return 0;
}

// Read the response headers, which are terminated by a blank line.
boost::asio::read_until(socket, response, "\r\n\r\n");

// Process the response headers.
std::string tmp;
while (std::getline(response_stream, tmp) && tmp != "\r")
header += tmp + "\n";

// Write whatever content we already have to output.
while (std::getline(response_stream, tmp))
content += tmp;

// Read until EOF, writing data to output as we go.
while (boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error))
{
response_stream.clear();
while (std::getline(response_stream, tmp))
content += tmp;
}

if (error != boost::asio::error::eof)
throw boost::system::system_error(error);

// Substitute CRs by a space
for (std::size_t i = 0; i < header.size(); i++)
if (header[i] == '\r')
header[i] = ' ';

for (std::size_t i = 0; i < content.size(); i++)
if (content[i] == '\r')
content[i] = ' ';

return status_code;
}
catch (std::exception &e)
{
MYLOG_PRINT(wayToPrint, "Exception: {}", e.what());
//std::cerr << "Exception: " << e.what() << std::endl;
return 0;
}
}
...全文
1286 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
heavyd 2020-06-15
  • 打赏
  • 举报
回复
有高人指点一下吗?谢谢!

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧