2017-07-17 17 views
0

基於boost的示例,我編寫了以下程序。它應該回答的連接與HTTP 200和小文:簡單的HTTP服務器因「連接重新定義」而失敗

#include <iostream> 
#include <sstream> 
#include <boost\asio.hpp> 
#include <ctime> 
using namespace std; 
using boost::asio::ip::tcp; 
int main(int argc, char** argv) 
{ 
    try 
    { 
     boost::asio::io_service io_service; 
     tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 40001)); 
     while (true) 
     { 
      tcp::socket socket(io_service); 
      acceptor.accept(socket); 
      //Aceitou uma conexao 
      time_t now = time(0); 
      stringstream ssHtml; 
      ssHtml << "HELLO WORLD "; 
      stringstream ssHttp; 
      ssHttp << "HTTP/1.1 200 OK\r\n"; 
      ssHttp << "Connection: close\r\n"; 
      ssHttp << "Content-Type: text/html\r\n"; 
      ssHttp << "Content-Length: " << ssHtml.str().size() <<"\r\n"; 
      ssHttp << ssHtml.str(); 
      ssHttp << "\r\n\r\n"; 
      boost::system::error_code ignored_error; 
      cout << ssHttp.str(); 
      boost::asio::write(socket, boost::asio::buffer(ssHttp.str()), ignored_error); 
     } 
    } 
    catch (std::exception &ex) 
    { 
     cerr << ex.what() << endl; 
    } 
    return 0; 
} 

但瀏覽器的請求失敗,「重新連接」。在調試服務器時,我看到它成功運行,將http響應打印到它的控制檯。

在firefox的devloper模式中,我看到響應到達,但由於某種原因瀏覽器說連接已被重新定義。出於某種原因,瀏覽器會在服務器上連接兩次,並且兩次都會失敗。 此外,防火牆已打開且端口是免費的。

我的問題是:我做錯了什麼?爲什麼這個簡單的服務器不能回答這個請求?爲什麼瀏覽器出現「連接重新定義」錯誤?

+0

兩個問題,我注意到:最後標題(「內容長度」)應與2個換行符結束,標誌着頭的端部,所述內容之後的2個換行符不需要;第二:你可能還應該閱讀瀏覽器的請求。 – ChrisBFX

回答

0

HTTP協議需要雙重線端以標記響應報頭的末尾。至少添加一個:

 ssHttp << "\r\n" << ssHtml.str(); 

而且,你可能會想,以避免發送以下內容的數據太(雖然有Connection: close頭的差別應該不是很明顯)無關行尾。

0

當我看到來自瀏覽器的請求,如ChrisBFX在評論上述建議,按計劃我的服務器的工作或多或少。瀏覽器發送迴應並且瀏覽器瞭解它。它還發送兩個答覆,而不是之一,但它不再與「連接重定向」失敗。

#include <iostream> 
#include <sstream> 
#include <boost\asio.hpp> 
#include <ctime> 
using namespace std; 
using boost::asio::ip::tcp; 
int main(int argc, char** argv) 
{ 
    try 
    { 
     boost::asio::io_service io_service; 

     tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 40001)); 
     while (true) 
     { 
      tcp::socket socket(io_service); 
      acceptor.accept(socket); 
/////////////-------------THIS SOLVED THE PROBLEM---------------------- 
      boost::asio::streambuf s_buf; 
      boost::asio::async_read_until(socket, s_buf, "\r\n\r\n", 
       std::bind([](const boost::system::error_code& ec){ 
       if (ec != 0) 
        std::cout << "error " << ec.value() << ", " << ec.message(); 
       }, 
       std::placeholders::_1)); 
      std::string message; 
      std::istream input_stream(&s_buf); 
      std::getline(input_stream, message); 
      std::cout << message << std::endl; 
///////////////------------------------------------------------------ 
      time_t now = time(0); 
      stringstream ssHtml; 
      ssHtml << "HELLO WORLD "; 
      stringstream ssHttp; 
      ssHttp << "HTTP/1.1 200 OK\r\n"; 
      ssHttp << "Connection: close\r\n"; 
      ssHttp << "Content-Type: text/html\r\n"; 
      ssHttp << "Content-Length: " << ssHtml.str().size();// << "\r\n"; 
      ssHttp << "\r\n\r\n"; 
      ssHttp << ssHtml.str();   
      boost::system::error_code ignored_error; 
      cout << ssHttp.str(); 
      boost::asio::write(socket, boost::asio::buffer(ssHttp.str()), ignored_error); 
     } 
    } 
    catch (std::exception &ex) 
    { 
     cerr << ex.what() << endl; 
    } 
    return 0; 
}