From 76424b75f4f302b575ef0b1e011b90a2f185a845 Mon Sep 17 00:00:00 2001 From: Denes Matetelki Date: Wed, 9 Nov 2011 13:15:56 +0100 Subject: [PATCH] TcpClient listens to reply with poll on a separate thread --- .gitignore | 2 + include/TcpClient.hpp | 37 +++++++++++----- other/tcpclient_main.cpp | 37 ++++++++++++++-- src/TcpClient.cpp | 95 ++++++++++++++++++++++++++++++++-------- 4 files changed, 138 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index 9a7ee35..0e1ccaa 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ gdb.out html/* test/testCppUtils test/testCppUtils.out +*.kate-swp + diff --git a/include/TcpClient.hpp b/include/TcpClient.hpp index 1aa07a4..e0422c4 100644 --- a/include/TcpClient.hpp +++ b/include/TcpClient.hpp @@ -1,6 +1,8 @@ #ifndef TCP_CLIENT_HPP #define TCP_CLIENT_HPP +#include "Thread.hpp" + #include #include @@ -16,29 +18,44 @@ public: TcpClient ( const std::string host, const std::string port ); - ~TcpClient(); + virtual ~TcpClient(); bool connect(); bool disconnect(); bool send(const std::string msg); - bool receive(std::string &reply); private: + virtual void msgArrived(const std::string) = 0; + virtual void onDisconnect() = 0; + + class WatcherThread : public Thread + { + public: + WatcherThread( TcpClient &data ); + + private: + void* run(); + bool receive(); + + TcpClient &m_tcpClient; + }; + bool openSocket(); bool closeSocket(); bool connectToHost(); - bool getHostInfo(struct addrinfo **servinfo); - void printHostDetails(struct addrinfo *servinfo); - bool connectToFirstAddress(struct addrinfo *servinfo); - - int m_socket; - std::string m_host; - std::string m_port; - bool m_connected; + bool getHostInfo(struct addrinfo **servinfo) const; + void printHostDetails(struct addrinfo *servinfo) const; + bool connectToFirstAddress(struct addrinfo *servinfo) const; + + int m_socket; + std::string m_host; + std::string m_port; + bool m_connected; + WatcherThread m_watcher; }; diff --git a/other/tcpclient_main.cpp b/other/tcpclient_main.cpp index 6acfbb0..55aeecf 100644 --- a/other/tcpclient_main.cpp +++ b/other/tcpclient_main.cpp @@ -7,21 +7,50 @@ #include #include + +class PrinterTcpClient : public TcpClient +{ +public: + PrinterTcpClient ( const std::string host, + const std::string port ) + : TcpClient(host, port) + { + TRACE; + } + +private: + + void msgArrived( const std::string msg) + { + TRACE; + LOG( Logger::DEBUG, std::string("Got msg: ").append(msg).c_str() ); + } + + void onDisconnect() + { + TRACE; + LOG( Logger::DEBUG, "What shall I do..." ); + } + +}; + int main( int argc, char * argv[] ) { Logger::createInstance(); Logger::init(std::cout); Logger::setLogLevel(Logger::FINEST); - TcpClient tcpclient("localhost", "4455"); + PrinterTcpClient tcpclient("localhost", "4455"); tcpclient.connect(); + sleep(2); tcpclient.send("madao"); + sleep(2); - std::string reply; - tcpclient.receive(reply); - std::cout << "got reply \"" << reply << "\"" << std::endl; +// std::string reply; +// tcpclient.receive(reply); +// std::cout << "got reply \"" << reply << "\"" << std::endl; tcpclient.disconnect(); diff --git a/src/TcpClient.cpp b/src/TcpClient.cpp index 0e2e2c7..645e3f0 100644 --- a/src/TcpClient.cpp +++ b/src/TcpClient.cpp @@ -7,6 +7,8 @@ #include #include // inet_ntop +#include + TcpClient::TcpClient( const std::string host, const std::string port ) @@ -14,8 +16,11 @@ TcpClient::TcpClient( const std::string host, , m_host(host) , m_port(port) , m_connected(false) + , m_watcher(*this) { TRACE; + + m_watcher.start(); } TcpClient::~TcpClient() @@ -23,6 +28,9 @@ TcpClient::~TcpClient() TRACE; disconnect(); + + m_watcher.stop(); + m_watcher.join(); } @@ -66,22 +74,6 @@ bool TcpClient::send(const std::string msg) } -bool TcpClient::receive(std::string &reply) -{ - TRACE; - - char buffer[256]; - ssize_t n = read(m_socket, buffer, 255); - if (n == -1) { - LOG( Logger::ERR, errnoToString("ERROR reading from socket. ").c_str() ); - return false; - } - reply = std::string(buffer, n); - - return true; -} - - bool TcpClient::openSocket() { TRACE; @@ -136,7 +128,7 @@ bool TcpClient::connectToHost() } -bool TcpClient::getHostInfo(struct addrinfo **servinfo) +bool TcpClient::getHostInfo(struct addrinfo **servinfo) const { TRACE; @@ -166,7 +158,7 @@ bool TcpClient::getHostInfo(struct addrinfo **servinfo) } -void TcpClient::printHostDetails(struct addrinfo *servinfo) +void TcpClient::printHostDetails(struct addrinfo *servinfo) const { TRACE; @@ -196,7 +188,7 @@ void TcpClient::printHostDetails(struct addrinfo *servinfo) } -bool TcpClient::connectToFirstAddress(struct addrinfo *servinfo) +bool TcpClient::connectToFirstAddress(struct addrinfo *servinfo) const { TRACE; @@ -224,3 +216,68 @@ bool TcpClient::connectToFirstAddress(struct addrinfo *servinfo) " connection refused.").c_str() ); return false; } + + +TcpClient::WatcherThread::WatcherThread( TcpClient &data ) + : m_tcpClient(data) +{ + TRACE; +} + + +void* TcpClient::WatcherThread::run() +{ + TRACE; + + while ( m_isRunning ) { + + struct timespec tm = {0,1000}; + nanosleep(&tm, &tm) ; + if ( m_tcpClient.m_connected ) { + + pollfd fds[1] ; + fds[0].fd = m_tcpClient.m_socket ; + fds[0].events = POLLIN | POLLPRI ; + fds[0].revents = 0 ; + + int ret = poll( fds , 1, 1000) ; + if ( ret == -1 ) { + LOG( Logger::ERR, errnoToString("ERROR at polling. ").c_str() ); + m_tcpClient.m_connected = false; + m_tcpClient.onDisconnect(); + } + + if ( ret != 0 && !receive() ) { + m_tcpClient.m_connected = false; + m_tcpClient.onDisconnect(); + } + + } + } + + return 0; +} + + +bool TcpClient::WatcherThread::receive() +{ + TRACE; + + char buffer[256]; + int len = recv( m_tcpClient.m_socket, buffer , 256, 0) ; + + if (len == -1) { + LOG( Logger::ERR, errnoToString("ERROR reading from socket. ").c_str() ); + return false; + } + + if (len == 0) { + LOG( Logger::DEBUG, "Connection closed by peer." ); + return false; + } + + std::string msg(buffer, len); + m_tcpClient.msgArrived(msg); + + return true; +} \ No newline at end of file