TcpClient update. new class: TcpServer

master
Denes Matetelki 13 years ago
parent 8d02e474b8
commit b1d47a8978

@ -21,19 +21,35 @@ public:
bool connectToHost(const std::string host,
const std::string port);
bool getHostInfo(const std::string host,
const std::string port,
struct addrinfo **servinfo) const;
void printHostDetails(struct addrinfo *servinfo) const;
bool connectToFirstAddress(struct addrinfo *servinfo) const;
bool bindToHost(const std::string host,
const std::string port );
protected:
int m_socket;
int m_socket;
int m_domain;
int m_type;
int m_protocol;
sockaddr m_addr;
socklen_t m_addrLen;
static bool convertNameInfo( sockaddr* addr,
socklen_t addrLen,
std::string &retAddr,
std::string &retService);
private:
bool connectToFirstAddress(struct addrinfo *servinfo);
bool bindToFirstAddress(struct addrinfo *servinfo);
int m_domain;
int m_type;
int m_protocol;
static bool getHostInfo(const std::string host,
const std::string port,
struct addrinfo **servinfo);
static void printHostDetails(struct addrinfo *servinfo);
};

@ -0,0 +1,45 @@
#ifndef TCP_SERVER_HPP
#define TCP_SERVER_HPP
#include "Socket.hpp"
#include <string>
#include <poll.h>
class TcpServer : public Socket
{
public:
TcpServer ( const std::string host,
const std::string port,
const int maxClients = 5 );
virtual ~TcpServer();
bool start();
void stop();
virtual void msgArrived(const int clientSocket,
const std::string msg) = 0;
private:
TcpServer(const TcpServer&);
TcpServer& operator=(const TcpServer&);
bool receive(const int clientSocket);
void addFd( int fd, short events );
void removeFd( int fd );
std::string m_host;
std::string m_port;
nfds_t m_maxclients;
bool m_running;
pollfd *m_fds;
nfds_t m_num_of_fds;
sockaddr m_addr;
socklen_t m_addrLen;
};
#endif // TCP_SERVER_HPP

@ -15,6 +15,7 @@ public:
void* join() const;
virtual void stop();
void sendSignal( const int nSignal ) const;
bool isRunning() const;
private:

@ -0,0 +1,49 @@
// gpp tcpServer_main.cpp -o client -I../include ../src/Logger.cpp ../src/TcpClient.cpp
#include "TcpServer.hpp"
#include "Logger.hpp"
#include <iostream>
#include <string>
class EchoTcpServer : public TcpServer
{
public:
EchoTcpServer ( const std::string host,
const std::string port,
const int maxClients = 5 )
: TcpServer(host, port, maxClients)
{
TRACE;
}
void msgArrived(const int clientSocket,
const std::string msg)
{
TRACE;
LOG( Logger::DEBUG, std::string("Got msg: ").append(msg).c_str() );
}
};
int main( int argc, char * argv[] )
{
Logger::createInstance();
Logger::init(std::cout);
Logger::setLogLevel(Logger::FINEST);
EchoTcpServer tcpServer("localhost", "4455");
tcpServer.start();
sleep(10);
tcpServer.stop();
Logger::destroy();
return 0;
}

@ -7,6 +7,7 @@
#include <sys/socket.h>
#include <arpa/inet.h> // inet_ntop
Socket::Socket(const int domain,
const int type,
const int protocol)
@ -14,6 +15,8 @@ Socket::Socket(const int domain,
, m_domain(domain)
, m_type(type)
, m_protocol(protocol)
, m_addr()
, m_addrLen(0)
{
TRACE;
@ -51,16 +54,16 @@ void Socket::closeSocket()
}
bool Socket::connectToHost(const std::string host,
const std::string port )
bool Socket::connectToHost( const std::string host,
const std::string port )
{
TRACE;
struct addrinfo *results(0);
if ( !getHostInfo(host, port, &results) )
if ( !Socket::getHostInfo(host, port, &results) )
return false;
printHostDetails(results);
Socket::printHostDetails(results);
if ( !connectToFirstAddress(results) )
return false;
@ -70,11 +73,74 @@ bool Socket::connectToHost(const std::string host,
}
bool Socket::bindToHost( const std::string host,
const std::string port )
{
TRACE;
struct addrinfo *results(0);
if ( !Socket::getHostInfo(host, port, &results) )
return false;
Socket::printHostDetails(results);
if ( !bindToFirstAddress(results) )
return false;
freeaddrinfo(results);
return true;
}
bool Socket::connectToFirstAddress(struct addrinfo *servinfo)
{
TRACE;
for ( struct addrinfo *it = servinfo; it != 0; it = it->ai_next)
if (::connect(m_socket, it->ai_addr, it->ai_addrlen) != -1) {
std::string address, service;
if ( convertNameInfo( it->ai_addr, it->ai_addrlen, address, service) ) {
LOG( Logger::DEBUG, std::string("Connected to ").
append(address).append(":").
append(service).c_str() );
}
return true;
}
LOG( Logger::ERR, "Could not connect to host, connection refused." );
return false;
}
bool Socket::bindToFirstAddress(struct addrinfo *servinfo )
{
TRACE;
for ( struct addrinfo *it = servinfo; it != 0; it = it->ai_next)
if (bind(m_socket, it->ai_addr, it->ai_addrlen) == 0) {
memcpy(&m_addr, it->ai_addr, it->ai_addrlen);
m_addrLen = it->ai_addrlen;
std::string address, service;
if ( Socket::convertNameInfo( &m_addr, m_addrLen, address, service) ) {
LOG( Logger::DEBUG, std::string("Binded to ").
append(address).append(":").
append(service).c_str() );
}
return true;
}
LOG( Logger::ERR, "Could not bind to host. Address already in use." );
return false;
}
bool Socket::getHostInfo( const std::string host,
const std::string port,
struct addrinfo **servinfo) const
struct addrinfo **servinfo)
{
TRACE;
TRACE_STATIC;
struct addrinfo hints;
@ -102,9 +168,9 @@ bool Socket::getHostInfo( const std::string host,
}
void Socket::printHostDetails(struct addrinfo *servinfo) const
void Socket::printHostDetails(struct addrinfo *servinfo)
{
TRACE;
TRACE_STATIC;
int counter(0);
for ( struct addrinfo *it = servinfo; it != 0; it = it->ai_next) {
@ -132,31 +198,28 @@ void Socket::printHostDetails(struct addrinfo *servinfo) const
}
bool Socket::connectToFirstAddress(struct addrinfo *servinfo) const
bool Socket::convertNameInfo(sockaddr* addr,
socklen_t addrLen,
std::string &retAddr,
std::string &retService)
{
TRACE;
TRACE_STATIC;
for ( struct addrinfo *it = servinfo; it != 0; it = it->ai_next)
if (::connect(m_socket, it->ai_addr, it->ai_addrlen) != -1) {
char hostBuffer[256];
char serviceBuffer[256];
int status = getnameinfo( it->ai_addr, it->ai_addrlen,
hostBuffer, sizeof(hostBuffer),
serviceBuffer, sizeof(serviceBuffer),
NI_NAMEREQD );
if ( status != 0 ) {
LOG( Logger::WARNING, std::string("Could not resolve hostname. ").
append(gai_strerror(status)).c_str() );
} else {
LOG( Logger::DEBUG, std::string("Connected to ").
append(hostBuffer).append(":").
append(serviceBuffer).c_str() );
}
return true;
}
char hostBuffer[256];
char serviceBuffer[256];
LOG( Logger::ERR, std::string("Could not connect to host,"
" connection refused.").c_str() );
return false;
int status = getnameinfo( addr, addrLen,
hostBuffer, sizeof(hostBuffer),
serviceBuffer, sizeof(serviceBuffer),
NI_NAMEREQD );
if ( status != 0 ) {
LOG( Logger::WARNING, std::string("Could not resolve hostname. ").
append(gai_strerror(status)).c_str() );
return false;
}
retAddr.assign(hostBuffer);
retService.assign(serviceBuffer);
return true;
}

@ -8,7 +8,7 @@
#include <arpa/inet.h> // inet_ntop
#include <poll.h>
#include <time.h>
TcpClient::TcpClient( const std::string host,
const std::string port )
@ -55,8 +55,10 @@ void TcpClient::disconnect()
closeSocket();
m_connected = false;
m_watcher.stop();
m_watcher.join();
if ( m_watcher.isRunning() ) {
m_watcher.stop();
m_watcher.join();
}
}
@ -64,6 +66,9 @@ bool TcpClient::send(const std::string msg)
{
TRACE;
if ( !m_connected )
return false;
ssize_t n = write(m_socket, msg.c_str(), msg.length());
if (n == -1) {
LOG( Logger::ERR, errnoToString("ERROR writing to socket. ").c_str() );
@ -85,20 +90,20 @@ void* TcpClient::WatcherThread::run()
{
TRACE;
struct timespec tm = {0,1000};
while ( m_isRunning ) {
struct timespec tm = {0,1000};
nanosleep(&tm, &tm) ;
if ( m_tcpClient.m_connected ) {
pollfd fds[1] ;
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() );
LOG( Logger::ERR, errnoToString("ERROR polling. ").c_str() );
m_tcpClient.m_connected = false;
m_tcpClient.onDisconnect();
}

@ -0,0 +1,170 @@
#include "TcpServer.hpp"
#include "Logger.hpp"
#include "Common.hpp"
#include <poll.h>
#include <stdlib.h>
TcpServer::TcpServer( const std::string host,
const std::string port,
const int maxClients )
: Socket(AF_INET, SOCK_STREAM)
, m_host(host)
, m_port(port)
, m_maxclients(maxClients)
, m_running(false)
, m_fds(0)
, m_num_of_fds(0)
, m_addr()
, m_addrLen(0)
{
TRACE;
m_fds = (pollfd*) malloc (sizeof(struct pollfd)*m_maxclients);
}
TcpServer::~TcpServer()
{
TRACE;
free(m_fds);
}
bool TcpServer::start()
{
TRACE;
if ( !openSocket() )
return false;
if ( !bindToHost(m_host, m_port) )
return false;
if ( listen(m_socket, 64) == -1 ) {
LOG( Logger::ERR, errnoToString("ERROR listening. ").c_str() );
return false;
}
addFd( m_socket, POLLIN | POLLPRI ) ;
m_running = true;
struct timespec tm = {0,1000};
while ( m_running ) {
nanosleep(&tm, &tm) ;
int ret = poll( m_fds , m_maxclients, 1000);
if ( ret == -1 ) {
LOG( Logger::ERR, errnoToString("ERROR polling. ").c_str() );
return false;
}
if ( ret == 0 ) // timeout
continue;
for ( nfds_t i = 0; i < m_num_of_fds; ++i ) {
if ( m_fds[i].revents != 0 ) {
if ( m_fds[i].fd == m_socket ) {
sockaddr clientAddr;
socklen_t clientAddrLen;
int client_socket = accept( m_socket, &clientAddr, &clientAddrLen ) ;
if ( client_socket == -1 ) {
LOG( Logger::ERR, errnoToString("ERROR accepting. ").c_str() );
} else {
std::string clientAddress, clientService;
if ( Socket::convertNameInfo(&clientAddr, clientAddrLen,
clientAddress, clientService ) ) {
LOG( Logger::DEBUG, std::string("New client connected: ").
append(clientAddress).append(":").
append(clientService).c_str() );
}
addFd( client_socket, POLLIN | POLLPRI );
}
}
else {
if ( !receive( m_fds[i].fd ) ) {
removeFd(m_fds[i].fd);
}
}
}
}
}
return true;
}
void TcpServer::stop()
{
TRACE;
m_running = false;
closeSocket();
}
bool TcpServer::receive(const int clientSocket)
{
TRACE;
char buffer[256];
int len = recv( clientSocket, 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);
msgArrived(clientSocket, msg);
return true;
}
void TcpServer::addFd( int fd, short events )
{
TRACE;
if (m_num_of_fds < m_maxclients )
{
m_fds[m_num_of_fds].fd = fd ;
m_fds[m_num_of_fds].events = events ;
m_fds[m_num_of_fds].revents = 0 ;
++m_num_of_fds ;
}
}
void TcpServer::removeFd( int fd )
{
TRACE;
unsigned int i = 0 ;
while (i < m_maxclients && m_fds[i].fd != fd ) ++i ;
if ( i != m_maxclients ) {
for ( ; i < m_maxclients - 1; ++i )
m_fds[i] = m_fds[i+1] ;
m_fds[i].fd = 0 ;
m_fds[i].events = 0 ;
m_fds[i].revents = 0 ;
--m_num_of_fds ;
}
}

@ -53,6 +53,12 @@ void Thread::sendSignal( const int nSignal ) const
}
bool Thread::isRunning() const
{
return m_isRunning;
}
void* Thread::threadStarter( void* pData )
{
TRACE_STATIC;

@ -1,75 +0,0 @@
#include "socketClient.hpp"
#include <errno.h> // errno
#include <string.h> // strerror
#include <iostream>
SocketClient::SocketClient( const int addrDomain,
const int socketType )
: m_connected(false)
, m_addrDomain(addrDomain)
, m_socketType(socketType)
, m_socketfd(0)
{
}
SocketClient::~SocketClient()
{
if ( m_connected && close(m_socketfd) == -1 )
std::cerr << errorToString("ERROR closing socket. ") << std::endl;
}
bool SocketClient::send(const std::string msg)
{
if ( !m_connected && !this->connect() )
return false;
ssize_t n = write(m_socketfd, msg.c_str(), msg.length());
if (n == -1) {
std::cerr << errorToString("ERROR writing to socket. ") << std::endl;
return false;
} else if ( n < (ssize_t)msg.length() ) {
std::cerr << "Only a part of msg has been written to socket. " << std::endl;
return false;
}
return true;
}
bool SocketClient::receive(std::string &reply)
{
if ( !m_connected && !this->connect() )
return false;
char buffer[256];
ssize_t n = read(m_socketfd, buffer, 255);
if (n == -1) {
std::cerr << errorToString("ERROR reading from socket. ") << std::endl;
return false;
}
reply = std::string(buffer, n);
return true;
}
bool SocketClient::connect(void)
{
m_socketfd = socket(m_addrDomain, m_socketType, 0);
if ( m_socketfd == -1 ) {
std::cerr << errorToString("ERROR opening socket. ") << std::endl;
return false;
}
return connectToPeer();
}
std::string SocketClient::errnoToString(const char *s)
{
return std::string(s).append(strerror(errno));
}

@ -18,7 +18,7 @@ if(CXXTEST_FOUND)
generated_main.cpp
Fixture.hpp
test_ArgParse.hpp
# test_ArgParse.hpp
# test_Singelton_call_once.hpp
# test_Singleton.hpp
# test_Singleton_meyers.hpp
@ -26,7 +26,7 @@ if(CXXTEST_FOUND)
# test_Mutex.hpp
# test_ScopedLock.hpp
# test_ConditionalVariable.hpp
# test_Thread.hpp
test_Thread.hpp
# test_ThreadPool.hpp
# test_Semaphore.hpp
# test_Timer.hpp

@ -111,4 +111,31 @@ public:
delete m2;
}
private:
class EmptyThreadClass : public Thread
{
private:
void* run( void ) {
TRACE;
return 0;
}
};
public:
void testEmpty( void )
{
TEST_HEADER;
EmptyThreadClass e;
e.start();
e.stop();
void *retVal = e.join();
TS_ASSERT_EQUALS ( retVal , (void *)0 );
}
};

Loading…
Cancel
Save