boost :: asio无法干净地关闭TCP连接

时间:2010-07-03 04:26:16

标签: c++ visual-c++ sockets boost-asio asyncsocket

我正在尝试实现一个简单的HTTP服务器。我能够将HTTP响应发送给客户端,但问题是在Firefox上我遇到“连接重置”错误。 IE也失败了,而Chrome完美运行并显示我在回复中发送的HTML。

如果我telnet到我的服务器,那么我会在响应之后收到“Connection Lost”消息。因此,我从中得出结论,连接没有得到正确关闭。以下是代码中的重要摘录。

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的析构函数。

1 个答案:

答案 0 :(得分:1)

服务器不应该关闭套接字。如果服务器关闭套接字并且客户端发送更多数据或接收队列中有数据,则客户端将收到导致此错误的RST。见http://cs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf

HTTP服务器应该读取整个客户端请求,或者在HTTP / 1.1的情况下读取整个客户端请求序列。在此示例中,它不读取任何客户端请求,因此接收队列中有数据,以便客户端收到重置。

在关闭前用一系列async_reads排空套接字 - 可能在将来你想要实际解析客户端请求; - )