Question

I have code that implements Poco SocketReactor, as described from Echo example.

class TSPConnectionHandler
{
    public:
        TSPConnectionHandler(const StreamSocket& socket, SocketReactor& reactor) :      _socket(socket),
                                                                                    _reactor(reactor)
        {
            _reactor.addEventHandler(_socket, Poco::NObserver<TSPConnectionHandler, ReadableNotification>(*this, &TSPConnectionHandler::onSocketReadable));
            _reactor.addEventHandler(_socket, Poco::NObserver<TSPConnectionHandler, WritableNotification>(*this, &TSPConnectionHandler::onSocketWritable));
            _reactor.addEventHandler(_socket, Poco::NObserver<TSPConnectionHandler, ShutdownNotification>(*this, &TSPConnectionHandler::onSocketShutdown));
            _reactor.addEventHandler(_socket, Poco::NObserver<TSPConnectionHandler, ErrorNotification>(*this, &TSPConnectionHandler::onSocketError));
            _reactor.addEventHandler(_socket, Poco::NObserver<TSPConnectionHandler, TimeoutNotification>(*this, &TSPConnectionHandler::onSocketTimeout));
        }
        virtual ~TSPConnectionHandler()
        {
            _reactor.removeEventHandler(_socket, Poco::NObserver<TSPConnectionHandler, ReadableNotification>(*this, &TSPConnectionHandler::onSocketReadable));
            _reactor.removeEventHandler(_socket, Poco::NObserver<TSPConnectionHandler, WritableNotification>(*this, &TSPConnectionHandler::onSocketWritable));
            _reactor.removeEventHandler(_socket, Poco::NObserver<TSPConnectionHandler, ShutdownNotification>(*this, &TSPConnectionHandler::onSocketShutdown));
            _reactor.removeEventHandler(_socket, Poco::NObserver<TSPConnectionHandler, ErrorNotification>(*this, &TSPConnectionHandler::onSocketError));
            _reactor.removeEventHandler(_socket, Poco::NObserver<TSPConnectionHandler, TimeoutNotification>(*this, &TSPConnectionHandler::onSocketTimeout));
        }

    void onSocketReadable(const Poco::AutoPtr<ReadableNotification>& pNf)
    {
        cout << "READable   !!" << endl;
      try
      {
        vector<char> m_buffer;
        m_buffer.resize(1024, '\0');
        LONG32 m_buflen = _socket.receiveBytes(&m_buffer[0], 1024);
        if (m_buflen == 0)
        {
          cout << "Connection reset by peer normally" << endl;
          delete this;
        }
        _socket.sendBytes(&m_buffer[0], m_buflen);
      }
      catch(Poco::Net::NetException& e)
      {
          cout << "socket read exception: " << e.displayText() << endl;
          delete this;
      }
    }
    void onSocketWritable(const Poco::AutoPtr<WritableNotification>& pNf)
    {
        cout << "WRITEable   !!" << endl;
    }
    void onSocketShutdown(const Poco::AutoPtr<ShutdownNotification>& pNf)
    {
        cout << "SHUTDOWN!!!!!!!!!!!!" << endl;
        delete(this);
    }
    void onSocketError(const Poco::AutoPtr<ErrorNotification>& pNf)
    {
        cout << "Error!!" << endl;
    }
    void onSocketTimeout(const Poco::AutoPtr<TimeoutNotification>& pNf)
    {
        cout << "Timeout!!" << endl;
    }

    private:
        StreamSocket _socket;
        SocketReactor& _reactor;
};

It starts normally somewhere else in program using this code:

Poco::Net::ServerSocket tcpsock("9495");
Poco::Net::SocketReactor reactor;
Poco::Net::SocketAcceptor<TSPConnectionHandler> acceptor(tcpsock, reactor);
Poco::Thread thread;
thread.start(reactor);

waitForTerminationRequest();

reactor.stop();
thread.join();
return Application::EXIT_OK;

Also I have python client to test it:

import socket

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 9495))
data = raw_input ( "Something:" )
client_socket.send(data)
data = client_socket.recv(1024)
print "RECIEVED:" , data
client_socket.close()

And I got list of questions that I don't understand how to resolve:

  • after python string "client_socket.connect(('localhost', 9495))" is done, server starts to spam "onSocketWritable", how to stop it? I understand I have to be notified if socket become writable, but why do it continue doing that while all socket's life? If that is normal situation, what for was designed WritableNotification?
  • if I will start python in debug mode and close it before "client_socket.close()", server gets exception and will be deleted throw "socket read exception: ". But errornotification and shutdownnotification will not be dispatched. Why? I never saw them dispatched anyhow.
  • If I will let "client_socket.close()" be done, on server side I will receive ReadableNotification and will leave throw "Connection reset by peer normally". But still there will be no ShutdownNotification. Why?
Was it helpful?

Solution

  1. As soon as you are connecting to the server a socket will be instantiated and if you registred a writable notification you will get notified about this state. This means only add this event handler when you have to send data. The socket will send the data and when done, this handler is called again (asynchronous socket...). If you don't have to send more block's call removeEventHandler for this event.

  2. The socket reactor uses the select command (Socket::select(readable, writable, except, _timeout)) The name errornotification is a little bit misleading (will get some error conditions but also out of bounds data). If a socket closes gracefully onReadable will be called with no available char's, otherwise Poco::Net::ConnectionResetException will be thrown.

  3. The ShutdownNotification is sent when the SocketReactor is stopped.

You should have a look in SocketRactor.cpp then everything is much clearer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top