3

単純なHTTPサーバーを実装しようとしています。HTTP応答をクライアントに送信できますが、問題はFirefoxで「接続リセット」エラーが発生することです。IEも失敗しますが、Chromeは完全に機能し、応答で送信したHTMLを表示します。

サーバーにTelnetで接続すると、応答の直後に「接続が失われました」というメッセージが表示されます。したがって、このことから、接続が適切に閉じられていないと結論付けました。以下は、コードからの重要なスニペットです。

class TCPServer-これにより、アクセプター(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();
}
   }

classTCPConnection-クライアントへの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;
}

私が言及しなければならない重要な点の1つは、TCPConnectionのオブジェクトは「スマートポインター」によってポイントされるため、TCPConnection :: handleWriteの実行が終了すると、このTCPConnectionオブジェクトをポイントするポインターが残っていないことです。したがって、handleWriteが終了した直後に、TCPConnectionのデストラクタが呼び出されます。

4

1 に答える 1

1

サーバーはソケットを閉じてはなりません。サーバーがソケットを閉じ、クライアントがさらにデータを送信するか、受信キューにデータがある場合、クライアントはRSTを受信して​​このエラーを引き起こします。http://cs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdfを参照してください

HTTPサーバーは、クライアント要求全体を読み取る必要があります。HTTP/ 1.1の場合は、クライアント要求のシーケンス全体を読み取る必要があります。この例では、クライアント要求を読み取らないため、受信キューにデータがあり、クライアントはリセットを受信します。

閉じる前に、async_readsのシーケンスでソケットをドレインします。おそらく将来的には、クライアント要求を実際に解析する必要があります;-)

于 2011-06-22T10:48:37.340 に答える