我很高兴看到有一个针对C++增强的TCP/IP套接字的跨平台标准。到目前为止,我已经能够为我遇到的所有主题找到帮助。但现在我陷入了一个奇怪的行为。我正在开发在2013年末的iMac上使用Xcode 7.3.1。boost :: asio :: read()在自定义web服务中阻塞
我正在开发一个特殊用途的简单网络服务器。下面的代码是削减版本,演示了这些不良行为:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
using namespace std;
using namespace boost;
using namespace boost::asio;
using namespace boost::asio::ip;
int main(int argc, const char * argv[]) {
static asio::io_service ioService;
static tcp::acceptor tcpAcceptor(ioService, tcp::endpoint(tcp::v4(), 2080));
while (true) {
// creates a socket
tcp::socket* socket = new tcp::socket(ioService);
// wait and listen
tcpAcceptor.accept(*socket);
asio::streambuf inBuffer;
istream headerLineStream(&inBuffer);
char buffer[1];
asio::read(*socket, asio::buffer(buffer, 1)); // <--- Yuck!
asio::write(*socket, asio::buffer((string) "HTTP/1.1 200 OK\r\n\r\nYup!"));
socket->shutdown(asio::ip::tcp::socket::shutdown_both);
socket->close();
delete socket;
}
return 0;
}
当我在某组的条件下访问该服务,浏览器会呛以20秒以上。如果我暂停在调试模式下运行的程序,我可以看到asio :: read()调用被阻塞。它从字面上等待甚至从浏览器出现单个字符。为什么是这样?
让我澄清一下,因为我在机器上重现此操作很奇怪。一旦我启动程序(用于调试),我从Chrome打开“页面”(如http://localhost:2080/)。我可以多次刷新刷新,并且工作得很好。但之后我使用Firefox(或Safari),它会挂起20秒,从而使页面按预期显示。现在得到这个。如果在Firefox中的这种延迟期间,我在Chrome中点击刷新,Firefox页面也会立即显示。在另一个实验中,我点击了Chrome中的Refresh(正常工作),然后在Firefox和Safari中都点击了刷新。他们两个都挂了。我在Chrome中点击刷新,所有3都立即显示。
在此实验的更改中,只要启动该程序,我就在Firefox或Safari中点击刷新,并且它们工作得很好。无论我刷新多少次。然后在他们之间来回走动。我毫不夸张地说把CMD-R快速刷新这些浏览器。但是,只要我在同一页面上刷新Chrome,然后尝试刷新其他两个浏览器,就会再次挂起。
自从1993年左右开始网络编程以来,我很了解HTTP标准。最基本的工作流程是浏览器启动TCP连接。只要Web服务器接受连接,客户端就会发送一个HTTP标头。类似于根页面(“/”)的“GET/\ r \ n \ r \ n”。服务器通常读取所有标题行并停止,直到它到达第一个空白行,这表示标题的结尾和上传内容的开始(例如POST的表单内容),Web应用程序可以自由使用或忽略。服务器在准备好自己的HTTP头时作出响应,通常以“HTTP/1.1 200 OK \ r \ n”开头,后面跟着实际的页面内容(或二进制文件内容等)。
在我的应用程序中,我实际上使用asio :: read_until(* socket,inBuffer,“\ r \ n \ r \ n”)来读取整个HTTP标头。既然这是悬挂,我想也许其他浏览器正在发送损坏的标题或其他东西。因此,我将样本修剪为仅读取单个字符(应该是“GET /”中的“G”)。一个字符。不。作为一个便笺,我知道我正在做同步,但我真的想要一个简单的线性演示来展示这种不良行为。我假设这不是什么导致这个问题,但我知道这是可能的。
这里有什么想法吗?在我的用例中,这是可以忍受的,因为服务器最终会做出响应,但是我真的很理解,消除这种不良行为。
无法在我的mac上重现它 – Arunmu
学习更多,我发现Chrome正在发出两个连接请求,其他浏览器只有一个。第一个带有一个HTTP头,但第二个没有。看起来这是Chrome中的一个错误。以下帖子提到: http://stackoverflow.com/questions/4761913/server-socket-receives-2-http-requests-when-i-send-from-chrome-and-receives-one –
我注意到了来自Chrome的两个请求,一个用于'/',另一个用于'favicon.ico',这两个请求看起来都很好。也许你正在使用旧版本的Chrome? – Arunmu