我正在尝试使用Boost.Asio编写一个非常简单的HTTP服务器。这是代码(几乎与Boost.Asio教程中的示例相同)
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <thread>
#include <chrono>
using boost::asio::ip::tcp;
int main()
{
try
{
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 12345));
for (;;)
{
tcp::socket socket(io_service);
acceptor.accept(socket);
const char message[] = "HTTP/1.0 200 OK\r\n\r\n<html><body><i>Hello, world</i></body></html>";
boost::system::error_code ignored_error;
boost::asio::write(socket, boost::asio::buffer(message), ignored_error);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
当我运行此示例时,我尝试使用地址为127.0.0.1:12345的Chrome,但它显示“此网页不可用”。但是,如果我在调试器中逐步启动,它会正确显示斜体“Hello,world”。实际上,如果我在写操作后添加一行std::this_thread::sleep_for(std::chrono::seconds(1));
,它将正常工作。我究竟做错了什么?有没有办法避免这种丑陋的黑客攻击?
我在Windows 7上使用Visual Studio 2013.编译为64位代码。
答案 0 :(得分:3)
<强>更新强>
客户可能需要Content-Length的想法可能有一些优点。
相反,您可以添加Connection: close
标题,这会阻止浏览器将其保持打开状态(因此,EOF&#39;将计为响应的结尾)。
代码看起来很好,它在我的盒子上没有睡眠(Ubuntu / Opera)。
唯一能让我感到震惊的是......有趣的是
您发送终止NUL
字符作为回复的一部分:
$ netcat localhost 12345 | xxd
0000000: 4854 5450 2f31 2e30 2032 3030 204f 4b0d HTTP/1.0 200 OK.
0000010: 0a0d 0a3c 6874 6d6c 3e3c 626f 6479 3e3c ...<html><body><
0000020: 693e 4865 6c6c 6f2c 2077 6f72 6c64 3c2f i>Hello, world</
0000030: 693e 3c2f 626f 6479 3e3c 2f68 746d 6c3e i></body></html>
0000040: 00 .
您没有收到请求;取决于客户端,这可能会使客户端稍微混淆(?)。我不认为这可能是问题所在,因为有一些宝贵的请求信息被分成包裹
更新实际上,如果您的浏览器执行其他请求(例如GET /favicon.ico
,例如并行),则可能会出现问题。您的服务器会同步处理连接,并且可能会同时到达。确保监听套接字允许在&#34;积压&#34;
这old answer ('08) says backlog
used to be 5 in Asio, by default。
答案 1 :(得分:2)
我认为问题是HTTP
问题而不是网络问题。
该邮件缺少Content-Length
标头,因此您的HTTP/1.1
客户端(Chrome)可能正在等待您的服务器关闭连接以标记邮件正文的结尾,请参阅:{{3}第4.4节。尝试将消息更改为:
"HTTP/1.0 200 OK\r\nContent-Length: 45\r\n\r\n<html><body><i>Hello, world</i></body></html>";
我希望我的邮件正文Content-Length
正确。 ;)
答案 2 :(得分:0)
我认为这里的问题是你没有等待请求。如果在发送请求之前套接字已关闭,则客户端会将此视为重置连接。你的一秒延迟技巧有效,因为它保持连接打开的时间足够长,以便客户端通过其请求发送。
如果我在写入之前添加一个虚拟请求侦听器,那么您的示例在没有延迟技巧的情况下工作:
std::array<char, 8192> ignored_buffer;
socket.async_read_some(boost::asio::buffer(ignored_buffer),
[](boost::system::error_code ec, std::size_t bytes_transferred) {});