Странные уведомления реактора Poco

У меня есть код, который реализует 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 «client_socket.connect ((‘localhost’, 9495))» завершена, сервер начинает рассылать спам «onSocketWritable», как это остановить? Я понимаю, что должен получить уведомление, если сокет станет доступным для записи, но почему он продолжает это делать, пока работает весь сокет? Если это нормальная ситуация, для чего был разработан WritableNotification?
  • если я запустлю python в режиме отладки и закрою его до «client_socket.close ()», сервер получит исключение и будет удален с помощью «socket readception:». Но уведомление об ошибке и уведомление о выключении не будут отправлены. Зачем? Я никогда не видел их отправленными в любом случае.
  • Если я позволю «client_socket.close ()» быть выполненным, на стороне сервера я получу ReadableNotification и оставлю команду throw «Сброс соединения обычным узлом». Но все равно не будет никакого уведомления о завершении работы. Зачем?

0

Решение

  1. Как только вы подключаетесь к серверу, будет создан экземпляр сокета, и если вы зарегистрируете доступное для записи уведомление, вы получите уведомление об этом состоянии.
    Это означает, что добавлять этот обработчик событий нужно только тогда, когда вам нужно отправить данные. Сокет будет отправлять данные, и когда это будет сделано, этот обработчик вызывается снова (асинхронный сокет …). Если вам не нужно отправлять больше вызовов блока, снимите removeEventHandler для этого события.

  2. В сокетном реакторе используется команда выбора (Socket :: select (читаемый, доступный для записи, кроме _timeout)). Уведомление об ошибке имени немного вводит в заблуждение (получит некоторые условия ошибки, но также и за пределами данных). Если сокет закрывается изящно, onReadable будет вызываться без доступных символов, в противном случае будет выдано исключение Poco :: Net :: ConnectionResetException.

  3. Уведомление о завершении работы отправляется, когда SocketReactor остановлен.

Вы должны заглянуть в SocketRactor.cpp, тогда все станет намного понятнее.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]