繁体   English   中英

POCO-我可以将SocketReactor用作客户端吗?

[英]POCO - can I use SocketReactor as a client?

当人们正在运行TCP服务器时,我看到了许多与SocketAcceptor结合使用的SocketReactor的示例。

但是,我想作为客户端连接到现有的TCP服务器,但希望能够处理SocketReactor公开的事件,例如onSocketReadable,onSocketWritable,onSocketShutdown,onSocketError和onSocketTimeout。

POCO库是否有可能? 我将以下代码放在一起,但没有触发任何事件。 如果这种方法不起作用,还有其他建议吗? 基本上,我将从服务器接收tcp消息的实时流,并且还将消息发送回服务器以执行某些任务。

class ITCHProvider
    {
    private:
        Poco::Net::SocketAddress _sa;
        Poco::Net::StreamSocket _sock;
        Poco::Net::SocketStream _stream;
        Poco::Net::SocketReactor _reactor;

    public:
        ITCHProvider() :
            _sa("host", 1234),
            _sock(),
            _stream(_sock),
            _reactor()
        {
            _reactor.addEventHandler(_sock, Poco::NObserver<ITCHProvider, Poco::Net::ReadableNotification>(*this, &ITCHProvider::onSocketReadable));
            _reactor.addEventHandler(_sock, Poco::NObserver<ITCHProvider, Poco::Net::WritableNotification>(*this, &ITCHProvider::onSocketWritable));
            _reactor.addEventHandler(_sock, Poco::NObserver<ITCHProvider, Poco::Net::ShutdownNotification>(*this, &ITCHProvider::onSocketShutdown));
            _reactor.addEventHandler(_sock, Poco::NObserver<ITCHProvider, Poco::Net::ErrorNotification>(*this, &ITCHProvider::onSocketError));
            _reactor.addEventHandler(_sock, Poco::NObserver<ITCHProvider, Poco::Net::TimeoutNotification>(*this, &ITCHProvider::onSocketTimeout));

            _sock.connect(_sa);
        }

        ~ITCHProvider()
        {
            close();
        }

        void onSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf)
        {
            LOG(INFO) << "READable   !!";
        }
        void onSocketWritable(const Poco::AutoPtr<Poco::Net::WritableNotification>& pNf)
        {
            LOG(INFO) << "WRITEable   !!";
        }
        void onSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf)
        {
            LOG(INFO) << "SHUTDOWN!!!!!!!!!!!!";
        }
        void onSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf)
        {
            LOG(INFO) << "Error!!";
        }
        void onSocketTimeout(const Poco::AutoPtr<Poco::Net::TimeoutNotification>& pNf)
        {
            LOG(INFO) << "Timeout!!";
        }

        // Close down the connection properly.
        void close() {
            try {
                _sock.shutdown();
            }
            catch (...) {
                LOG(INFO) << "closing failed.";
            }
        }

    };

可以做到,但是请注意,(a)在您实际运行反应堆之前什么也不会发生,并且(b)反应堆将一直旋转直到明确停止为止,因此最好在单独的线程中运行;

这是一个简单的例子:

// server-side handler
class EchoServiceHandler {
public:
    EchoServiceHandler(StreamSocket& socket, SocketReactor& reactor): _socket(socket), _reactor(reactor) {
        _reactor.addEventHandler(_socket, Observer<EchoServiceHandler, ReadableNotification>(*this, &EchoServiceHandler::onReadable));
    }

    ~EchoServiceHandler() {
        _reactor.removeEventHandler(_socket, Observer<EchoServiceHandler, ReadableNotification>(*this, &EchoServiceHandler::onReadable));
    }

    void onReadable(ReadableNotification* pNf) {
        pNf->release();
        char buffer[8];
        int n = _socket.receiveBytes(buffer, sizeof(buffer));
        if (n > 0) {
            _socket.sendBytes(buffer, n);
        }
        else {
            _socket.shutdownSend();
            delete this;
        }
    }

    private:
        StreamSocket   _socket;
        SocketReactor& _reactor;
};

您的原始代码,稍作修改:

class ITCHProvider : public Poco::Runnable
{
private:
    Poco::Net::StreamSocket _sock;
    Poco::Net::SocketReactor _reactor;

public:
    ITCHProvider(const SocketAddress& sa) : _sock(sa) {
        _reactor.addEventHandler(_sock, Poco::NObserver<ITCHProvider, Poco::Net::ReadableNotification>(*this, &ITCHProvider::onSocketReadable));
        _reactor.addEventHandler(_sock, Poco::NObserver<ITCHProvider, Poco::Net::WritableNotification>(*this, &ITCHProvider::onSocketWritable));
        _reactor.addEventHandler(_sock, Poco::NObserver<ITCHProvider, Poco::Net::ShutdownNotification>(*this, &ITCHProvider::onSocketShutdown));
        _reactor.addEventHandler(_sock, Poco::NObserver<ITCHProvider, Poco::Net::ErrorNotification>(*this, &ITCHProvider::onSocketError));
        _reactor.addEventHandler(_sock, Poco::NObserver<ITCHProvider, Poco::Net::TimeoutNotification>(*this, &ITCHProvider::onSocketTimeout));
        std::string data = "Hello reactor world!";
        _sock.sendBytes(data.data(), (int)data.length());
    }

    ~ITCHProvider() { close(); }

    void run() { _reactor.run(); }
    void stop() { _reactor.stop(); }

    void onSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) {
        std::cout << "READable   !!" << std::endl;
        char data[1025] = { 0 };
        if (_sock.receiveBytes(data, 1024) > 0) {
            std::cout << data << std::endl;
        }
    }
    void onSocketWritable(const Poco::AutoPtr<Poco::Net::WritableNotification>& pNf) {
        std::cout << "WRITEable   !!" << std::endl;
    }
    void onSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
        std::cout << "SHUTDOWN!!!!!!!!!!!!" << std::endl;
    }
    void onSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf) {
        std::cout << "Error!!" << std::endl;
    }
    void onSocketTimeout(const Poco::AutoPtr<Poco::Net::TimeoutNotification>& pNf) {
        std::cout << "Timeout!!" << std::endl;
    }

    void close() {
        try {
            _sock.shutdown();
        }
        catch (...) {
            std::cout << "closing failed." << std::endl;
        }
    }
};

现在,让我们运行上面的代码:

SocketAddress ssa;
ServerSocket ss(ssa);
SocketReactor reactor;
SocketAcceptor<EchoServiceHandler> acceptor(ss, reactor);
Thread server;
server.start(reactor);
ITCHProvider provider(SocketAddress("127.0.0.1", ss.address().port()));
Thread client;
client.start(provider);
Thread::sleep(1000);
reactor.stop();
provider.stop();
server.join();
client.join();

输出(为清晰起见,可写和超时通知已静音):

READable   !!
Hello reactor world!
SHUTDOWN!!!!!!!!!!!!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM