实验目的
1. 处理一个 http 请求 2. 接收并解析 http 请求 3. 从服务器文件系统中获得被请求的文件 4. 创建一个包括被请求的文件的 http 响应信息 5. 直接发送该信息到客户端
具体内容
一、C++ 程序来实现 web 服务器功能。
二、用 HTML 语言编写两个 HTML文件,并制作两个网页,来验证 web 服务器能否成功运行。
三、验证处理http请求和应对错误请求显示错误信息两种情况。
实验过程
用HTML 语言编写制作三个简易网页:1. 主页,包括欢迎信息和一个跳转链接;2. 跳转页,包含一个图片和提示信息;3. 404错误处理页,当跳转到无法访问的地址时就来到这个页面。
编写C++代码,使用Boost.Asio库,用来处理 TCP 连接和数据的读写。
使用Boost.Filesystem获取文件的扩展名和检查文件是否存在。监听8888端口的访问以及实现一些获取返回信息和跳转页面的逻辑。然后编译链接运行
Linux运行在虚拟机环境中,先通过ifconfig获取局域网内的IP:192.168.146.138,然后在物理机上运行浏览器,在地址栏中输入192.168.146.138:8888进入主页,依次测试跳转和输入错误地址的情况。
关键代码讲解
主要处理逻辑代码,首先,它读取请求行(方法、路径和协议),然后根据路径找到相应的文件。如果文件不存在,它会返回一个 404 错误页面;如果文件存在,它会返回文件的内容。主函数中只需创建了一个 TCP 接受器,然后进入一个无限循环,接受新的连接并处理请求。
void handle_request(tcp::socket& socket) {
try {
boost::asio::streambuf request;
boost::asio::read_until(socket, request, "\r\n");
std::string method, path, protocol;
std::istream request_stream(&request);
request_stream >> method >> path >> protocol;
if (path == "/") {
path = "/index.html";
}
std::string full_path = root_dir + path;
std::ifstream file(full_path, std::ios::binary);
boost::asio::streambuf response;
std::ostream response_stream(&response);
if (!file) {
// Open the 404.html file
std::ifstream file_404(root_dir + "/404.html", std::ios::binary);
if (!file_404) {
response_stream << "HTTP/1.0 500 Internal Server Error\r\n";
response_stream << "Connection: close\r\n\r\n";
std::cout << "Response: 500 Internal Server Error" << std::endl;
} else {
response_stream << "HTTP/1.0 404 Not Found\r\n";
response_stream << "Content-Type: text/html\r\n";
response_stream << "Connection: close\r\n\r\n";
response_stream << file_404.rdbuf();
std::cout << "Response: 404 Not Found" << std::endl;
}
}
else {
response_stream << "HTTP/1.0 200 OK\r\n";
response_stream << "Content-Type: " << get_content_type(full_path) << "\r\n";
response_stream << "Connection: close\r\n\r\n";
response_stream << file.rdbuf();
std::cout << "Response: 200 OK, Content-Type: " << get_content_type(full_path) << std::endl;
}
boost::asio::write(socket, response);
socket.shutdown(tcp::socket::shutdown_both);
} catch (boost::system::system_error& e) {
if (e.code() != boost::asio::error::eof) {
throw; // Rethrow if it's not the expected exception.
}
// Handle EOF exception here if necessary.
std::cout << "Connection closed by client." << std::endl;
}
}
运行示例
(1)当输入IP:8888实现访问主页。
(2)当点击“Next Page”,会转到下一个界面,展示预设好的内容。
(3)当输入一个错误的网址时,例如aaa.html,将会显示404界面。
相关代码
BJTU_CS_Learning/computernetwork at main · JJLi0427/BJTU_CS_Learning (github.com)