boost :: asio не может закрыть TCP соединение - PullRequest
3 голосов
/ 03 июля 2010

Я пытаюсь реализовать простой HTTP-сервер.Я могу отправить HTTP-ответ клиентам, но проблема в том, что в Firefox я получаю ошибку «Сброс подключения».IE тоже не работает, в то время как Chrome работает отлично и отображает HTML-код, который я отправил в ответе.

Если я подключаюсь к своему серверу, я получаю сообщение «Соединение потеряно» сразу после ответа.Итак, из этого я заключил, что соединение не закрывается должным образом.Ниже приведены важные фрагменты кода.

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();
}
   }

класс 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.

1 Ответ

1 голос
/ 22 июня 2011

Сервер не должен закрывать сокет.Если сервер закрывает сокет и клиент отправляет больше данных или в очереди приема есть данные, клиент получит RST, вызывающий эту ошибку.См. http://cs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf

Сервер HTTP должен прочитать весь клиентский запрос или, в случае HTTP / 1.1, всю последовательность клиентских запросов.В этом примере он не читает ни один из клиентских запросов, поэтому в очереди приема есть данные, поэтому клиент получает сброс.

Перед закрытием опустите сокет с последовательностями async_reads - возможно, в будущемвы действительно захотите разобрать клиентский запрос; -)

...