奇怪的poco reactor的通知

时间:2014-04-09 08:47:21

标签: c++ poco-libraries reactor

我有实现Poco SocketReactor的代码,如Echo示例所述。

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;
};

它使用此代码正常启动程序中的其他位置:

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;

我也有python客户端来测试它:

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()

我得到了一些我不明白如何解决的问题:

  • 在python string&#34; client_socket.connect((&#39; localhost&#39;,9495))&#34;完成后,服务器开始垃圾邮件&#34; onSocketWritable&#34;,如何阻止它?我知道如果套接字变成可写的话我必须得到通知,但是为什么它会在所有套接字的生命中继续这样做?如果这是正常情况,那么什么设计为WritableNotification?
  • 如果我将在调试模式下启动python并在&#34; client_socket.close()&#34;之前关闭它,则服务器获取异常并将被删除throw&#34;套接字读取异常:&#34;。但是不会发送错误通知和关闭通知。为什么?无论如何我从没见过他们。
  • 如果我将&#34; client_socket.close()&#34;完成后,在服务器端,我将收到ReadableNotification并将离开throw&#34;连接正常通过对等方重置&#34;。但仍然没有ShutdownNotification。为什么?

1 个答案:

答案 0 :(得分:2)

  1. 一旦连接到服务器,就会实例化套接字,如果您注册了可写通知,您将收到有关此状态的通知。 这意味着只有在必须发送数据时才添加此事件处理程序。套接字将发送数据,完成后,再次调用此处理程序(异步套接字...)。如果您不必为此事件发送更多阻止调用removeEventHandler。

  2. 套接字反应器使用select命令(Socket :: select(可读,可写,除了_timeout))名称错误通知有点误导(会得到一些错误条件,但也会超出边界数据)。如果一个套接字正常关闭onReadable将被调用而没有可用的char,否则将抛出Poco :: Net :: ConnectionResetException。

  3. 当SocketReactor停止时发送ShutdownNotification。

  4. 你应该看看SocketRactor.cpp然后一切都更清楚。