You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
5.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//
// NetworkRequest.cpp
//
// Created by duzixi.com on 15/8/25.
//
#include "NetworkRequest.h"
using namespace std;
using boost::asio::ip::tcp;
/// POST请求
string PostRequest(char* host, char* path, string form) {
long length = form.length();
// 声明Asio基础: io_service任务调度机
boost::asio::io_service io_service;
// 获取服务器终端列表
tcp::resolver resolver(io_service);
tcp::resolver::query query(host, "http");
tcp::resolver::iterator iter = resolver.resolve(query);
// 尝试连接每一个终端直到成功建立socket连接
tcp::socket socket(io_service);
boost::asio::connect(socket, iter);
// 构建网络请求头
// 指定 "Connection: close" 在获取应答后断开连接,确保获文件全部数据。
boost::asio::streambuf request;
ostream request_stream(&request);
request_stream << "POST " << path << " HTTP/1.1\r\n";
request_stream << "Host: " << host << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Content-Type:application/x-www-form-urlencoded\r\n";
request_stream << "Content-Length: " << length << "\r\n";
request_stream << "Connection: close\r\n\r\n"; // 注意这里是两个空行
request_stream << form; //POST 发送的数据本身不包含多于空行
// 发送请求
boost::asio::write(socket, request);
// 读取应答状态. 应答缓冲流 streambuf 会自动增长至完整的行
// 该增长可以在构造缓冲流时通过设置最大值限制
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
// 检查应答是否OK.
istream response_stream(&response);// 应答流
string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
string status_message;
getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/") {
printf("无效响应\n");
}
if (status_code != 200) {
printf("响应返回 status code %d\n", status_code);
}
// 读取应答头部,遇到空行后停止
boost::asio::read_until(socket, response, "\r\n\r\n");
// 显示应答头部
string header;
int len = 0;
while (getline(response_stream, header) && header != "\r") {
if (header.find("Content-Length: ") == 0) {
stringstream stream;
stream << header.substr(16);
stream >> len;
}
}
long size = response.size();
if (size > 0) {
// .... do nothing
}
// 循环读取数据流,直到文件结束
boost::system::error_code error;
while (boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error)) {
// 获取应答长度
size = response.size();
if (len != 0) {
cout << size << " Byte " << (size * 100) / len << "%\n";
}
}
if (error != boost::asio::error::eof) {
throw boost::system::system_error(error);
}
cout << size << " Byte 内容已下载完毕." << endl;
// 将streambuf类型转换为string类型返回
istream is(&response);
is.unsetf(ios_base::skipws);
string sz;
sz.append(istream_iterator<char>(is), istream_iterator<char>());
// 返回转换后的字符串
return sz;
}
/// GET请求
string GetRequest(char* host, char* path) {
// 声明Asio基础: io_service任务调度机
boost::asio::io_service io_service;
// 获取服务器终端列表
tcp::resolver resolver(io_service);
tcp::resolver::query query(host, "http");
tcp::resolver::iterator iter = resolver.resolve(query);
// 尝试连接每一个终端直到成功建立socket连接
tcp::socket socket(io_service);
boost::asio::connect(socket, iter);
// 构建网络请求头.
// 指定 "Connection: close" 在获取应答后断开连接,确保获文件全部数据。
boost::asio::streambuf request;
ostream request_stream(&request);
request_stream << "GET " << path << " HTTP/1.1\r\n";
request_stream << "Host: " << host << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
// 发送请求
boost::asio::write(socket, request);
// 读取应答状态. 应答缓冲流 streambuf 会自动增长至完整的行
// 该增长可以在构造缓冲流时通过设置最大值限制
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
// 检查应答是否OK.
istream response_stream(&response);
string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
string status_message;
getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/") {
printf("响应无效\n");
}
if (status_code != 200) {
printf("响应返回 status code %d\n", status_code);
}
// 读取应答头部,遇到空行后停止
boost::asio::read_until(socket, response, "\r\n\r\n");
// 显示应答头部
string header;
int len = 0;
while (getline(response_stream, header) && header != "\r") {
if (header.find("Content-Length: ") == 0) {
stringstream stream;
stream << header.substr(16);
stream >> len;
}
}
long size = response.size();
if (size > 0) {
// ... do nothing ...
}
boost::system::error_code error; // 读取错误
// 循环读取数据流,直到文件结束
while (boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error)) {
// 获取应答长度
size = response.size();
if (len != 0) {
cout << size << " Byte " << (size * 100) / len << "%" << endl;
}
}
// 如果没有读到文件尾,抛出异常
if (error != boost::asio::error::eof) {
throw boost::system::system_error(error);
}
cout << size << " Byte 内容已下载完毕." << endl;
// 将streambuf类型转换为string类型并返回
istream is(&response);
is.unsetf(ios_base::skipws);
string sz;
sz.append(istream_iterator<char>(is), istream_iterator<char>());
return sz;
}
/// GET请求(重载)
string GetRequest(string url) {
size_t index;
// 去掉url中的协议头
if (url.find("http://") != string::npos) {
url = url.substr(7);
}
printf("url:%s\n", url.c_str());
// 截取host字符串
index = url.find("/");
char* host = new char[index];
strcpy(host, url.substr(0, index).c_str());
// 截取urlPath字符串
char* urlPath = new char[url.length() - index + 1];
strcpy(urlPath, url.substr(index, url.length() - index).c_str());
return GetRequest(host, urlPath);
}