У меня есть код, который реализует 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()
И я получил список вопросов, которые я не понимаю, как решить:
Как только вы подключаетесь к серверу, будет создан экземпляр сокета, и если вы зарегистрируете доступное для записи уведомление, вы получите уведомление об этом состоянии.
Это означает, что добавлять этот обработчик событий нужно только тогда, когда вам нужно отправить данные. Сокет будет отправлять данные, и когда это будет сделано, этот обработчик вызывается снова (асинхронный сокет …). Если вам не нужно отправлять больше вызовов блока, снимите removeEventHandler для этого события.
В сокетном реакторе используется команда выбора (Socket :: select (читаемый, доступный для записи, кроме _timeout)). Уведомление об ошибке имени немного вводит в заблуждение (получит некоторые условия ошибки, но также и за пределами данных). Если сокет закрывается изящно, onReadable будет вызываться без доступных символов, в противном случае будет выдано исключение Poco :: Net :: ConnectionResetException.
Уведомление о завершении работы отправляется, когда SocketReactor остановлен.
Вы должны заглянуть в SocketRactor.cpp, тогда все станет намного понятнее.
Других решений пока нет …