Archived

This forum has been archived. Please start a new discussion on GitHub.

How to capture the interruption of connection.

as the example in ice-demo. I did a test for bidir, but it can not capture the exception when the connection disconnects. so , what can I do for capture this event when the connection disconnects.

in the file ice-demos/cpp/Ice/bidir/CallbackI.cpp , The following is for push data, it should throw a exception when the connection disconnects, but not.
try{(*p)->callback(num); catch(const Exception& ex){}

void
CallbackSenderI::run()
{
cout << "run invoke.\n";
int num = 0;
bool destroyed = false;
while(!destroyed)
{
cout << "destroyed=" << destroyed << endl;

    std::set<Demo::CallbackReceiverPrx> clients;
    {
        IceUtil::Monitor<IceUtil::Mutex>::Lock lck(*this);
        timedWait(IceUtil::Time::seconds(2));

        if(_destroy)
        {
            destroyed = true;
            continue;
        }

        clients = _clients;
    }

    cout << "clients.size()" << clients.size()<<endl;

    if(!clients.empty())
    {
        ++num;
        for(set<CallbackReceiverPrx>::iterator p = clients.begin(); p != clients.end(); ++p)
        {
            try
            {
                cout << "clients=" <<  _communicator->identityToString((*p)->ice_getIdentity()) << endl;
                (*p)->callback(num); //通知客户算
            }
            catch(const Exception& ex)
            {
                //通知客户端失败
                cout << "removing client `" << _communicator->identityToString((*p)->ice_getIdentity()) << "':\n"
                     << ex << endl;

                IceUtil::Monitor<IceUtil::Mutex>::Lock lck(*this);
                _clients.erase(*p);
            }
            catch (...)
            {
                cout << "unknow execption" << endl;
            }
        }
    }
}

}

Comments

  • like this, how to use on the server side.

    class CallbackI : public Ice::ConnectionCallback
    {
    virtual void heartbeat(const Ice::ConnectionPtr& connection)
    {
    std::cout << "received heartbeat for connection:\n" <<
    connection->toString() << std::endl;
    }
    virtual void closed(const Ice::ConnectionPtr& connection)
    {
    std::cout << "connection closed:\n" << connection->toString() <<
    std::endl;
    }
    };
    Ice::ObjectPrx proxy = communicator->stringToProxy(...);
    Ice::ConnectionPtr connection proxy->ice_getConnection();
    connection->setACM(5, Ice::CloseOnInvocationAndIdle, Ice::HeartbeatAlways);
    connection->setCallback(new CallbackI());

  • benoit
    benoit Rennes, France

    Hi,

    The callback() invocation on the proxy should definitely raise an exception if the connection has been closed. Of course, the exception will be raised only if you call on the proxy.

    On the server side, you can get a reference on the connection using the con data member of the Ice::Current parameter:

    void
    CallbackSenderI::addClient(const Identity& ident, const Current& current)
    {
        IceUtil::Monitor<IceUtil::Mutex>::Lock lck(*this);
        CallbackReceiverPrx client = CallbackReceiverPrx::uncheckedCast(current.con->createProxy(ident));
        current.con->setCallback(new CallbackI());
        _clients.insert(client);
    }
    

    Cheers,
    Benoit.

  • Hi Benoit,
    I had a try on server side like the following, and I have received the heartbeat event ,but the closed event is not be striked.
    I want to do some thing when the connection disconnects, but now I can not capture the event. What should I do?

    class ConnectionCallbackI : public Ice::ConnectionCallback
    {

    virtual void heartbeat(const Ice::ConnectionPtr& connection)
    {
        LOG_DEBUG("received heartbeat:" << connection->toString());
    }
    virtual void closed(const Ice::ConnectionPtr& connection)
    {
        LOG_DEBUG("connection closed:" << id << "\n" << connection->toString());
    }
    

    };
    current.con->setCallback(new ConnectionCallbackI());

  • benoit
    benoit Rennes, France

    Hi,

    The closed operation should be called when the connection is closed (assuming there are enough threads in the thread pool to call it). Did you enable network tracing to confirm that the connection was actually closed?

    Cheers,
    Benoit.

  • Hi Benoit,
    as follows,the heartbeat is ok. but it only throw a exception in the ice frame when the connection is closed. the closed function is not be Invoked. and the next is my parameter Settings. threads is enough.
    and using the demo bidir for test. it is also the situation.

    [2016-09-07 13:56:02] [TradeSessionI.h:heartbeat:31]DEBUG: received heartbeat:local address = 121.40.36.116:20011
    remote address = 121.40.36.116:47717
    [2016-09-07 13:56:23] [TradeSessionI.h:heartbeat:31]DEBUG: received heartbeat:local address = 121.40.36.116:20011
    remote address = 121.40.36.116:47717

    -- 09/07/16 13:56:36.394 ./tdctp_svr: Network: closed tcp connection
    local address = 121.40.36.116:20011
    remote address = 121.40.36.116:47717
    !! 09/07/16 13:56:36.395 ./tdctp_svr: error: connection callback exception:
    ConnectionI.cpp:3198: Ice::CloseConnectionException:
    protocol error: connection closed
    local address = 121.40.36.116:20011
    remote address = 121.40.36.116:47717

    initData.properties = Ice::createProperties(argc, argv);
    initData.properties->setProperty(nameserver.c_str(), ss.str().c_str());
    initData.properties->setProperty("Ice.Warn.Connections", "1");
    initData.properties->setProperty("Ice.Trace.Network", "1");
    initData.properties->setProperty("Ice.ThreadPool.Server.Size", "50");
    initData.properties->setProperty("Ice.ThreadPool.Server.SizeMax", "500");

    initData.properties->setProperty("Ice.ACM.Close", "4");
    initData.properties->setProperty("Ice.ACM.Heartbeat", "0");
    initData.properties->setProperty("Ice.ACM.Timeout", "15");

    modify for bidir test:
    void
    CallbackSenderI::addClient(const Identity& ident, const Current& current)
    {
    IceUtil::Monitor::Lock lck(*this);

    cout << "adding client `" << _communicator->identityToString(ident) << "'"<< endl;
    
    CallbackReceiverPrx client = CallbackReceiverPrx::uncheckedCast(current.con->createProxy(ident));
    _clients.insert(client);
    
    current.con->setACM(5, Ice::CloseOnInvocationAndIdle, Ice::HeartbeatAlways);
    current.con->setCallback(new ConnectionCallbackI());
    

    }

    the result:
    received heartbeat:local address = 127.0.0.1:10000
    remote address = 127.0.0.1:33026
    received heartbeat:local address = 127.0.0.1:10000
    remote address = 127.0.0.1:33026
    !! 09/08/16 09:05:02.387 ./server: error: connection callback exception:
    ConnectionI.cpp:3198: Ice::CloseConnectionException:
    protocol error: connection closed
    local address = 127.0.0.1:10000
    remote address = 127.0.0.1:33026