简体   繁体   English

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

[英]boost::asio fails to close TCP connection cleanly

I am trying to implement a simple HTTP server. 我正在尝试实现一个简单的HTTP服务器。 I am able to send the HTTP response to clients but the issue is that on Firefox I get "Connection Reset" error. 我能够将HTTP响应发送给客户端,但问题是在Firefox上我遇到“连接重置”错误。 IE too fails, while Chrome works perfectly and displays the HTML I sent in the response. IE也失败了,而Chrome完美运行并显示我在响应中发送的HTML。

If I telnet to my server then I get "Connection Lost" message, just after the response. 如果我telnet到我的服务器然后在响应之后收到“Connection Lost”消息。 So, from this I concluded that connection is not getting closed properly. 因此,我从中得出结论,连接没有得到正确关闭。 Below are important snippets from the code. 以下是代码中的重要摘录。

class TCPServer - This initiates the acceptor (boost::asio::ip::tcp::acceptor) object. 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 - Represents a TCP connection to client. class TCPConnection - 表示与客户端的TCP连接。 This extends - public boost::enable_shared_from_this<TCPConnection> 这扩展了 - 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;
}

One important point that I should mention is that since objects of TCPConnection are pointed to by 'smart pointers' so when execution of TCPConnection::handleWrite finishes then there are no pointers left to point at this TCPConnection object. 我应该提到的一点是,由于TCPConnection的对象是由“智能指针”指向的,因此当TCPConnection :: handleWrite的执行完成时,没有指针指向此TCPConnection对象。 So immediately after handleWrite finishes, the TCPConnection's destructor is called. 所以在handleWrite完成后立即调用TCPConnection的析构函数。

The server should not close the socket. 服务器不应该关闭套接字。 If the server closes the socket and the client sends more data or there is data in the receive queue then the client will receive a RST causing this error. 如果服务器关闭套接字并且客户端发送更多数据或接收队列中有数据,则客户端将收到导致此错误的RST。 See http://cs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf http://cs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf

The HTTP server should read the entire client request or in the case of HTTP/1.1 the entire sequence of client requests. HTTP服务器应该读取整个客户端请求,或者在HTTP / 1.1的情况下读取整个客户端请求序列。 In this example it does not read any of the client request so there is data in the receive queue, so that the client receives a reset. 在此示例中,它不读取任何客户端请求,因此接收队列中有数据,以便客户端收到重置。

Drain the socket with a sequences of async_reads before closing - probably in the future you will want to actually parse the client request ;-) 在关闭之前用一系列async_reads排空套接字 - 可能在将来你想要实际解析客户端请求;-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Boost.Asio TCP移动到套接字析构函数不足以干净地关闭吗? - Boost.Asio TCP moved-to socket destructor not enough to cleanly close? boost :: asio干净地断开连接 - boost::asio cleanly disconnecting Boost ASIO 异步 TCP 日间服务器示例失败,响应超过 65536 字节时出现“对等连接重置” - Boost ASIO Asynchronous TCP daytime server example fails with "Connection reset by peer" on responses over 65536 bytes 当连接失败时,Boost ASIO ip tcp iostream expires_from_now不会导致错误 - Boost ASIO ip tcp iostream expires_from_now doesn't result in an error when connection fails 是否存在boost :: iostreams(双向)设备用于阻塞boost :: asio TCP连接? - Is there a boost::iostreams (bidirectional) Device for a blocking boost::asio TCP connection? 连接刚好-&gt;服务器TCP boost.ASIO后,连接丢失 - Connection lost just after connection -> Server TCP boost.ASIO boost :: asio :: tcp :: socket关闭并取消,不调用处理程序 - boost::asio::tcp::socket Close and cancel without handlers being called 使用boost :: asio :: ip :: tcp :: socket :: cancel()和socket :: close() - Using boost::asio::ip::tcp::socket::cancel() and socket::close() Boost asio中的TCP客户端 - TCP client in Boost asio 如何使用boost :: asio序列化UDP发现和TCP连接的类 - How to serialise classes for UDP discover and TCP connection using boost::asio
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM