/
Inicio :: Foros

 F.A.Q.F.A.Q.                  Conéctese para revisar sus mensajesConéctese para revisar sus mensajes   

Error con aplicación que se connecta a internet: Socket/C++!

 
      Índice del Foro elrincondelc.com -> Programación en Servidores
Ver tema anterior :: Ver siguiente tema  
AutorMensaje
IIBlackfoxII



Registrado: 12 Jul 2009
Mensajes: 2
Ubicación: In The Web

MensajePublicado: 12/07/2009 6:51 pm
Título: Error con aplicación que se connecta a internet: Socket/C++!

Bueno, la aplicación teóricamente es sencilla. me explico.

para manejar los datos, creé una socket class estándar, que bien puede ser utilizada para crear un "servidor" o para un "cliente". para profundizar un poco voy a mencionar sus métodos, eso sí, sin explicarlos cada uno:
esta sería la cabecera socket.h:
Código:

  1 #ifndef SOCKET
  2 #define SOCKET
  3
  4 #include <sys/types.h>
  5 #include <sys/socket.h>
  6 #include <string>
  7 #include <arpa/inet.h>
  8 #include <cstdio>
  9
 10
 11 #define PORT 3059
 12 #define MAXCONNECTIONSALLOW 10
 13 #define MAXRECV 500
 14
 15 using std::string;
 16
 17 class Socket{
 18     public:
 19
 20         bool create();
 21
 22         // Server
 23
 24         bool bind();
 25         bool listen();
 26         bool acept();
 27
 28         // Client
 29
 30         bool connect(const string remote_h, const int remote_port);
 31
 32
 33         // Send and Recive Data
 34
 35         int recv(string &data) const;
 36         int send(const string data) const;
 37     private:
 38         int m_sock;
 39 };
 40 #endif


los métodos para server no han sido declarados, solo declaro un supuesto prototipo que usaré en el futuro. Por ahora lo que me interesa es el client.

vale, basandome en esta socket class cree una client class que llamo TcpClient, la cual, basandondome en un ejemplo que encontré en la web, hereda los métodos de socket class de modo privado, es decir:

Código:
class TcpClient: private Socket


posteriormente uso los métodos de Socket de la siguiente manera (dentro de TcpClient):

Código:
bool TcpClient::method(void)
{
   Socket::sockmethod(arg0);
}

Aclaro que este modo de usarlo no lo comprendo muy bien, pues cómo dije antes, me basé en un ejemplo totalmente funcional. Cuando digo modo de usarlo, me refiero a la herencia, es decir, con mi Exp. como programador de PHP, he aprendido que cuando usas una sentencia del tipo class::method(agrs) es porque no estás heredando nada, simplemente accedes a un método de la clase que no necesita la previa creación de un objeto. En este caso en concreto la Socket class usa una variable que resulta implícita (el manejador del socket), y que, según tengo entendido en la teoría OOP, necesita que se cree el objeto, pero si los métodos que supuestamente se heredaron de socket, se están usando accediendo directamente a la clase, no entiendo cómo es que en el ya citado "ejemplo de la web" funcione correctamente, a caso este es un, para mí, nuevo tipo de herencia? es decir, una herencia simple y dura?.
para que el forero entienda lo que quiero decir, explicaré como es la herencia que yo conozco.
primero declaras lo que conozco como instancia de otra clase, es decir, una clase que hereda los métodos de otra, que en C++ sería así (Corrijanme si me equivoco):

Código:
class subclass: class supclass{
   ...
};


y ya está, es decir, todos los métodos heredados se pueden usar tal cual, para invocarlos se hace como si no heredara, según tengo entendido:

Código:
object_supclass.method();
object_subclass.method();


es esto correcto?

bueno, el caso es que hipotéticamente hasta aquí todo debería funcionar, independientemente de lo que yo tenga como sabido (la teoría), todo esto es solo chachará que me ayuda a encaminar al forero a mi problema...


es de destacar que para la TcpClient class modifiqué los operadores << y >> para que el objeto creado a partir de esta clase fuera usado de un modo parecido de como se usa el cout y el cin, y todos los flujos en general...

La TcpClient solo cuenta con un constructor que ejecutaría las conexiones del socket y los modificadores antes mencionados.

El operador >> lo que haría sería basicamente invocar al método recv del socket.
El operador << invocaría el send.

Cuando todo esto está hecho, o sea, programado, sigue programar el main.
el main simplemente me pide unos datos para crear el socket, el host y el puerto, y luego me pide unos datos para hacer un HTTPRequest. por último crea el socket, envía los datos, y recibe el resultado.

al compilar me salta este error desde el main:

/tmp/ccoqrai8.o: In function `main':
main.cpp:(.text+0x49a): undefined reference to `TcpClient::TcpClient(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)'
main.cpp:(.text+0x4d8): undefined reference to `TcpClient::operator<<(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const'
main.cpp:(.text+0x4ea): undefined reference to `TcpClient::operator>>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&) const'
collect2: ld returned 1 exit status

y no sé porqué, se que tiene que ver con la TcpClient class pero no se en qué me equivoco, para que me puedan ayudar más he aquí el código de tcpclient.h y tcpclient.cpp:

tcpclient.h:


Código:
  1 #ifndef TCPCLIENT
  2 #define TCPCLIENT
  3
  4 #include "socket.h"
  5 #include "exception.h"
  6
  7 using std::string;
  8
  9 class TcpClient : private Socket{
 10     public:
 11
 12         TcpClient(string rh, int prt);
 13
 14
 15         const TcpClient &operator << (const string &data) const;
 16         const TcpClient &operator >> (string &data) const;
 17 };
 18 #endif


tcpclient.cpp:

Código:
  1 #include "tcpclient.h"
  2 #include "exception.h"
  3
  4 using std::string;
  5
  6 TcpClient::TcpClient(string rh, int prt){
  7     if(!Socket::create())
  8         throw Exception("Socket couldn't be created");
  9
 10     if(!Socket::connect(rh, prt))
 11         throw Exception("Socket coultn't be connected with remote host");
 12 }
 13
 14 const TcpClient &TcpClient::operator << (const string &data) const{
 15     if(!Socket::send(data))
 16         throw Exception("Data couldn't be sent");
 17     return *this;
 18 }
 19
 20 const TcpClient &TcpClient::operator >> (string &data) const{
 21     if(!Socket::recv(data))
 22         throw Exception("Data couldn't be recived");
 23     return *this;
 24 }


en el main este es el fragmento de código que invoca a la TcpClient class:
Código:

 65     try{
 66         string Response;
 67         TcpClient socket(r_host, port);
 68
 69         socket << httpRequest;
 70         socket >> Response;
 71
 72         cout << "la Respuesta del servidod fue: " << endl << Response;
 73
 74     }catch(Exception e){
 75         e.showexception();
 76         return -1;
 77     }


Espero no haberme enrollado mucho y que alguien me pueda ayudar..., gracias de antemano.
_________________
....
Volver arriba
daltomi



Registrado: 28 Abr 2007
Mensajes: 335
Ubicación: Argentina

MensajePublicado: 13/07/2009 8:10 am
Título:

Buenas.
El error, me parece, que es de enlazado. Si puedes compilar manualmente deberias hacerlo parecido a esto: (en mi caso con GCC)
Código:
g++ -o salida.bin TcpClient.cpp Socket.cpp Main.cpp

o más "a mano":
Código:

g++ -c TcpClient.cpp
g++ -c Socket.cpp
g++ -c Main.cpp
g++ -o salida.bin TcpClient.o Socket.o Main.o

Otra cosa: los operadores << y >> podrias implementarlos de ésta manera:
Código:
const void operator<< (const string&) const;
Sin retorno de ningún tipo.
Las llamadas a la funciones miembros de la clase base Socket desde la derivada no sería necesario que sea explícita[ if(!Socket::create()) ] , debería el compilador resolver el ámbito sin problemas en éste caso,(creo porque no puedo compilarlo para probar si hay o no ambiguedades sueltas quién sabe dónde)

Saludo.
Volver arriba
Dirección AIM
IIBlackfoxII



Registrado: 12 Jul 2009
Mensajes: 2
Ubicación: In The Web

MensajePublicado: 14/07/2009 12:17 am
Título:

déjame decirte, señor daltomi, Wink que tiene mucha razón, ese era mi problema, es que la experiencia que he tenido con C++ no me había llevado a la situación de varios source files, siempre había trabajado con el main o con headers que estaban completos. y aunque ya sabía que primero se compilan los source para crear los objetos y posteriormente se compilan los objetos para crear el ejecutable, me vi en la situación de que al no practicar, se me había olvidado por completo.

es más, creí que con solo incluir la cabecera, es decir #include "header.h" ya se incluía el archivo que lo definía, header.cpp, gravísimo error, jeje

En cualquier caso muchísimas gracias por la ayuda, y espero tropezarme con otro problema para volver a pasarme por este grandioso foro.

"déjenme comentar que mi aprendizaje en C++ ha sido muy progresivo, aunque al principio fue lento, pronto fui descubriendo que son muchas las páginas que ofrecen una base de datos con toda la info, bien en español o en inglés, sobre C/C++ y sus librerías, y foros tan importantes como este que ofrecen ayuda. Con esto solo quiero decir que C/C++ son lenguajes con mucho apoyo, y que por tanto si eres alguien que no conoce bien este lenguaje y desea comenzar con el, no estarás solo en esta comunidad tan grande"

"no es lo mismo que con php.net donde está todo. sino mejor, pues en cada web te explican lo máximo abarcable y desde diferentes puntos de vista"
_________________
....
Volver arriba
      Índice del Foro elrincondelc.com -> Programación en Servidores
Página 1 de 1Todas las horas están en GMT - 8 Horas

 
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas

(c) ElRincondelC.com

Un proyecto de UrlanHeat.com