Boost logo

Boost Users :

Subject: [Boost-users] asio Socket disconnection not working in 1.38?
From: Michael Dehmlow (dehmlowm_at_[hidden])
Date: 2009-02-26 13:35:42


I'm trying to detect that a peer has been disconnected using the asio socket
library. Below is a source listing of a unit test that I have created (which
is one of several that I have tried; ask for more listings if nesasary) to
figure out a reliable method to do so.

I've also tried using (and have unit test listings for) the
availble(errorCode) call the sock1.remote_endpoint(errorCode); calls.

I need a way to detect that a client has been disconnected from my server
without blocking.

I've even tried using the read_some call with the io_control non_blocking
option set but the then read some returns an error every time read_some is
called.

[code]
for(int i=0;i<1;i++)
{
    boost::asio::io_service ioServ1;
    boost::asio::io_service ioServ2;
    boost::asio::io_service ioServ3;
    boost::asio::io_service ioServ4;

    boost::asio::ip::tcp::socket sock1(ioServ1);
    
    boost::asio::ip::tcp::socket sock3(ioServ3);

    SocketAcceptor sA1(ioServ1,sock1,std::string("localHost"),8321);
    SocketAcceptor sA2(ioServ3,sock3,std::string("localHost"),8322);

    // The socket acceptor class simple starts a thread and and
accept(_mySocket,ec)
    // with a boost::asio::ip::tcp::acceptor. If thread does not completed
in the time passed in
    //the milliseconds then the call then the the accept call will return.
    sA1.accept(10);
    sA2.accept(10);

    boost::asio::ip::tcp::socket sock2(ioServ2);
    boost::asio::ip::tcp::socket sock4(ioServ4);

    boost::asio::ip::tcp::resolver resolver1(ioServ2);
    boost::asio::ip::tcp::resolver::query query1(boost::asio::ip::tcp::v4(),
"localhost", (boost::lexical_cast<std::string>(8321)).c_str());
    boost::asio::ip::tcp::resolver::iterator iterator1 =
resolver1.resolve(query1);

    boost::asio::ip::tcp::resolver resolver2(ioServ4);
    boost::asio::ip::tcp::resolver::query query2(boost::asio::ip::tcp::v4(),
"localhost", (boost::lexical_cast<std::string>(8322)).c_str());
    boost::asio::ip::tcp::resolver::iterator iterator2 =
resolver2.resolve(query2);

    sock2.connect(*iterator1);
    sock4.connect(*iterator2);

    TS_ASSERT_EQUALS(sA1.accept(200),true);
    TS_ASSERT_EQUALS(sA2.accept(200),true);
    boost::system::error_code errorCode;

    //std::cout<<"about to read some from socket"<<std::endl;
    //boost::asio::socket_base::non_blocking_io command(true);
    //sock1.io_control(command);

    //TS_ASSERT_EQUALS(sock1.read_some(boost::asio::buffer(data, length),
errorCode),0);
    //std::cout<<"Hopefully that didn't take long"<<std::endl;

    sock2.close();
    sock4.close();

    //just a boost wrapped sleep call
    Thread::sleep(2000);

    //this assertion will always fail just used to see what is in the
errorCode object.
    TS_ASSERT_EQUALS(boost::asio::error::eof,errorCode);

    sock1.available(errorCode);
    TS_ASSERT(errorCode);
    TS_ASSERT_EQUALS(boost::asio::error::eof,errorCode);

    sock2.available(errorCode);
    TS_ASSERT(errorCode);
    TS_ASSERT_EQUALS(boost::asio::error::eof,errorCode);

    //TS_ASSERT_EQUALS(sock3.read_some(boost::asio::buffer(data, length),
errorCode),0);
    //TS_ASSERT_EQUALS(boost::asio::error::eof,errorCode);
    // TS_ASSERT(errorCode);

    sock3.available(errorCode);
    TS_ASSERT(errorCode);
    TS_ASSERT_EQUALS(boost::asio::error::eof,errorCode);

    sock3.available(errorCode);
    TS_ASSERT(errorCode);
    TS_ASSERT_EQUALS(boost::asio::error::eof,errorCode);

    //TS_ASSERT_EQUALS(sock2.read_some(boost::asio::buffer(data, length),
errorCode),0);
    //TS_ASSERT_EQUALS(boost::asio::error::eof,errorCode);
    //TS_ASSERT(errorCode);

    sock4.available(errorCode);
    TS_ASSERT(errorCode);
    TS_ASSERT_EQUALS(boost::asio::error::eof,errorCode);

    //TS_ASSERT_EQUALS(sock4.read_some(boost::asio::buffer(data, length),
errorCode),0);
    //TS_ASSERT_EQUALS(boost::asio::error::eof,errorCode);

    //TS_ASSERT(errorCode);

    TS_ASSERT(!sock1.is_open());
    TS_ASSERT(!sock3.is_open());
}
[/code]
The output:

//expected failure
 Error: Expected (boost::asio::error::eof == errorCode), found ({ 02 00 00
00 } != { 00 00 00 00 38 A4 63 00 })

//sock1 no errorCode
 Error: Assertion failed: errorCode
//sock1 no errorCode
 Error: Expected (boost::asio::error::eof == errorCode), found ({ 02 00 00
00 } != { 00 00 00 00 38 A4 63 00 })

//--------------------------------
//sock2 ALWAYS returns an errorcode
//--------------------------------
//sock2 some other errorCode

 Error: Expected (boost::asio::error::eof == errorCode), found ({ 02 00 00
00 } != { 19 27 00 00 38 A4 63 00 })

//sock3 no errorCode
 Error: Assertion failed: errorCode

 Error: Expected (boost::asio::error::eof == errorCode), found ({ 02 00 00
00 } != { 00 00 00 00 38 A4 63 00 })
//sock4 no errorCode
Error: Assertion failed: errorCode
 Error: Expected (boost::asio::error::eof == errorCode), found ({ 02 00 00
00 } != { 00 00 00 00 38 A4 63 00 })

//--------------------------------
//sock4 ALWAYS returns an errorcode
//--------------------------------
//sock4 some other errorCode

 Error: Expected (boost::asio::error::eof == errorCode), found ({ 02 00 00
00 } != { 19 27 00 00 38 A4 63 00 })
//is_open doesn't seem all that helpful either
 Error: Assertion failed: !sock1.is_open()
 Error: Assertion failed: !sock3.is_open()

-- 
View this message in context: http://www.nabble.com/asio-Socket-disconnection-not-working-in-1.38--tp22230650p22230650.html
Sent from the Boost - Users mailing list archive at Nabble.com.

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net