Ciao e grazie della tua risposta ora mi è più chiaro. Ogni giorno capisco sempre qualcosa in più.
Oggi ho fatto delle prove come mi hai detto tu passando new_sock come copia. Il problema è che se lo passo come copia la funzione serviceroutine non funziona e errno sulla socket mi restituisce un "Bad file descriptor" ora credo che questo sia dovuto a come è fatta la classe socket.
Ti dico che questa l'ho trovata in internet e non l'ho compresa fino in fondo. Quindi ti chiederei se puoi darmi una mano a comprenderla.
codice:
// Definition of the Socket class
#ifndef Socket_class
#define Socket_class
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
const int MAXHOSTNAME = 200;
const int MAXCONNECTIONS = 5;
const int MAXRECV = 500;
using namespace std;
class Socket
{
public:
Socket();
virtual ~Socket();
// Server initialization
/**
*\brief Imposta il socket e le sue opzioni
*\return true se l'operazione ha avuto successo
*/
bool create();
/**
*\brief Effettua il binding in caso di server
*\param [in] port contiene la porta sulla quale effettuare il binding
*\return true se l'operazione ha avuto successo
*/
bool bind ( const long port );
/**
*\brief Imposta il socket in modalità ascolto.
*\return true se l'operazione ha avuto successo
*/
bool listen() const;
/**
*\brief permette di accettare connessioni in ingresso sulla porta sulla quale si è in ascolto
*\param [out] Socket& contiene il nuovo socket per gestire la connessione
*\return true se l'operazione ha avuto successo
*/
bool accept ( Socket& ) const;
// Client initialization
/**
*\brief Permette di connettersi ad un server
*\param [in] host contiene l'indirizzo al quale connettersi
*\param [in] port contiene la porta sulla quale connettersi
*\return true se l'operazione ha avuto successo
*/
bool connect ( const std::string host, const long port );
// Data Transimission
/**
*\brief permette di inviare informazioni attraverso il socket
*\param [in] s puntatore all'array di caratteri che contiene l'informazione da inviare
*\param [in] len contiene la lunghezza dell'array
*\return true se l'operazione ha avuto successo
*/
bool send ( unsigned char * s, int len ) const;
/**
*\brief Permette la lettura di informazioni dal socket
*\param [out] s contiene l'informazione letta dal socket
*\return il numero di byte letti.
*/
int recv ( unsigned char * s ) const;
/**
*\brief Metodo che permette di impostare il socket come non bloccante
*\param [in] Se true imposta il socket come non bloccante
*/
void set_non_blocking ( const bool );
/**
*\brief Metodo che serve per identificare se il socket è ancora valido
*\return true in caso il socket sia ancora valido
*/
bool is_valid() const
{
return m_sock != -1;
}
void chiudi();
private:
int m_sock;
sockaddr_in m_addr;
};
#endif
Socket.cpp
codice:
// Implementation of the Socket class.
#include "Socket.h"
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <iostream>
Socket::Socket() :
m_sock ( -1 )
{
memset ( &m_addr,
0,
sizeof ( m_addr ) );
}
Socket::~Socket()
{
if ( is_valid() )
::close ( m_sock );
}
bool Socket::create()
{
m_sock = socket ( AF_INET,
SOCK_STREAM,
0 );
if ( ! is_valid() )
return false;
// TIME_WAIT - argh
int on = 1;
if ( setsockopt ( m_sock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 )
return false;
return true;
}
bool Socket::bind ( const long port )
{
if ( ! is_valid() )
{
return false;
}
m_addr.sin_family = AF_INET;
m_addr.sin_addr.s_addr = INADDR_ANY;
m_addr.sin_port = htons ( port );
int bind_return = ::bind ( m_sock,
( struct sockaddr * ) &m_addr,
sizeof ( m_addr ) );
if ( bind_return == -1 )
{
return false;
}
return true;
}
bool Socket::listen() const
{
if ( ! is_valid() )
{
return false;
}
int listen_return = ::listen ( m_sock, MAXCONNECTIONS );
if ( listen_return == -1 )
{
return false;
}
return true;
}
bool Socket::accept ( Socket& new_socket ) const
{
int addr_length = sizeof ( m_addr );
new_socket.m_sock = ::accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length );
if ( new_socket.m_sock <= 0 )
return false;
else
return true;
}
bool Socket::send ( unsigned char * s, int len ) const
{
int status = ::send ( m_sock, s, len, MSG_NOSIGNAL );
if ( status == -1 )
{
return false;
}
else
{
return true;
}
}
int Socket::recv ( unsigned char * s ) const
{
unsigned char buf [ MAXRECV + 1 ];
memset ( buf, 0, MAXRECV + 1 );
int status = ::recv ( m_sock, buf, MAXRECV, 0 );
if(-1 == status)
{
switch(errno)
{
case EAGAIN :// no messages
break;
case EBADF :
cerr << "Bad file descriptor" << endl;
break;
case ECONNRESET :
cerr << "Connection reset" << endl;
break;
case EINTR :
cerr << "Signal interrupt" << endl;
break;
case ENOTCONN :
cerr << "Not connected" << endl;
break;
case ENOTSOCK :
cerr << "Not a socket" << endl;
break;
case EOPNOTSUPP :
cerr << "Not supported" << endl;
break;
case ETIMEDOUT :
cerr << "Timed out" << endl;
break;
default :
cerr<<"Unknown" <<endl;
break;
}
}
if ( status == -1 )
{
std::cout << "status == -1 errno == " << errno << " in Socket::recv\n";
return 0;
}
else if ( status == 0 )
{
return 0;
}
else
{
memcpy(s,buf,status);
return status;
}
}
bool Socket::connect ( const std::string host, const long port )
{
if ( ! is_valid() ) return false;
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons ( port );
int status = inet_pton ( AF_INET, host.c_str(), &m_addr.sin_addr );
if ( errno == EAFNOSUPPORT ) return false;
status = ::connect ( m_sock, ( sockaddr * ) &m_addr, sizeof ( m_addr ) );
if ( status == 0 )
return true;
else
return false;
}
void Socket::set_non_blocking ( const bool b )
{
int opts;
opts = fcntl ( m_sock,
F_GETFL );
if ( opts < 0 )
{
return;
}
if ( b )
opts = ( opts | O_NONBLOCK );
else
opts = ( opts & ~O_NONBLOCK );
fcntl ( m_sock,
F_SETFL,opts );
}
void Socket::chiudi()
{
close(m_sock);
}
La classe l'ho presa da qui http://tldp.org/LDP/LG/issue74/tougher.html