2010-07-03 43 views
3

我想實現一個簡單的HTTP服務器。我能夠將HTTP響應發送給客戶端,但問題是,在Firefox中,我收到「連接重置」錯誤。 IE瀏覽器也失敗,而Chrome瀏覽器完美工作,並顯示我在響應中發送的HTML。boost :: asio無法關閉TCP連接乾淨

如果我telnet到我的服務器,然後我收到「連接丟失」的消息,只是在響應後。所以,從這個我得出的結論是連接沒有正確關閉。以下是代碼中的重要摘要。

class TCPServer - 這會啓動acceptor(boost :: asio :: ip :: tcp :: acceptor)對象。

void TCPServer::startAccept() 
{ 
    TCPConnection::pointer clientConnection = 
     TCPConnection::create(acceptor.io_service()); 

    acceptor.async_accept(clientConnection->getSocket(), 
     boost::bind(&TCPServer::handleAccept, this, clientConnection, 
    boost::asio::placeholders::error)); 
} 

void TCPServer::handleAccept(TCPConnection::pointer clientConnection, 
    const boost::system::error_code& error) 
    { 
    std::cout << "Connected with a remote client." << std::endl; 
if (!error) 
{ 
    clientConnection->start(); 
    startAccept(); 
} 
    } 

class TCPConnection - 表示到客戶端的TCP連接。這擴展 - public boost::enable_shared_from_this<TCPConnection>

TCPConnection::TCPConnection(boost::asio::io_service& ioService) 
: socket(ioService) 
{ 
} 
TCPConnection::~TCPConnection(void) 
{ 
    std::cout << "TCPConnection destructor called." << std::endl; 
} 

TCPConnection::pointer TCPConnection::create(boost::asio::io_service& ioService) 
{ 
    return pointer(new TCPConnection(ioService)); 
} 

tcp::socket& TCPConnection::getSocket() 
{ 
    return socket; 
} 

void TCPConnection::start() 
{ 
//ASSUME outBuf has some data.. It is initialized elsewhere. 
    boost::asio::async_write(socket, boost::asio::buffer(*outBuf), 
    boost::bind(&TCPConnection::handleWrite, shared_from_this(), 
    boost::asio::placeholders::error, 
    boost::asio::placeholders::bytes_transferred)); 
    std::cout << "Transferring " << outBuf->size() << " bytes." << std::endl; 
} 

void TCPConnection::handleWrite(const boost::system::error_code& err, size_t bytesTransferred) 
{ 
    std::cout << "Sent " << bytesTransferred << " bytes. Error:: " << err << std::endl; 
    socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both); 
    socket.close(); 
    std::cout << "TCP connection closed." << std::endl; 
} 

,我應該提到一個很重要的一點是,由於TCPConnection的對象由「智能指針」指出,所以當TCPConnection :: handleWrite的執行結束則沒有指針留在點這個TCPConnection對象。所以在handleWrite完成後立即調用TCPConnection的析構函數。

+0

你有什麼期望在寫處理程序發生時,你的TCPConnection對象超出範圍?看起來你所描述的行爲與你的代碼一致,在發送socket關閉的響應之後。 – 2010-07-03 20:53:54

回答

1

服務器不應關閉套接字。如果服務器關閉套接字並且客戶端發送更多數據或接收隊列中有數據,則客戶端將收到導致此錯誤的RST。請參閱http://cs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf

HTTP服務器應該讀取整個客戶機請求,或者在HTTP/1.1的情況下讀取整個客戶機請求序列。在此示例中,它不讀取任何客戶端請求,因此接收隊列中有數據,因此客戶端會收到重置。

瀝乾插座與async_reads收盤前一個序列 - 可能在未來你將要實際解析客戶端請求;-)