Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > C++ Builder
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 06-03-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 12
aguml Va por buen camino
Ando bastante liado con todo esto y por ahora tengo este codigo aunque falta por dejarlo como quiero pero poco a poco:
Código PHP:
#include <stdio.h>
#include <windows.h>

#define MAX_THREADS 2

DWORD WINAPI MyThreadFunctionLPVOID lpParam );
void ErrorHandler(LPTSTR lpszFunction);

int main(int argcchar *argv[]){

    
DWORD   dwThreadIdArray[MAX_THREADS];
    
HANDLE  hThreadArray[MAX_THREADS];
    
int i;

    for(
i=0i<MAX_THREADSi++ )
    {
        
// Creo el hilo para iniciar la ejecución en su función

        
hThreadArray[i] = CreateThread
            
NULL,                   // default security attributes
            
0,                      // use default stack size  
            
MyThreadFunction,       // thread function name
            
0,                      // argument to thread function
            
0,                      // use default creation flags 
            
&dwThreadIdArray[i]);   // returns the thread identifier

        // Compruebo el valor de retorno
        // Si CreateThread falla, termino la ejecución
        // Esto limpiará automáticamente los hilos y la memoria

        
if (hThreadArray[i] == NULL
        {
           
ErrorHandler("CreateThread");
           
ExitProcess(3);
        }
    } 
// Fin del bucle de creacion de hilos

    // Espero a que terminen todos los hilos
    
WaitForMultipleObjects(MAX_THREADShThreadArrayTRUEINFINITE);

    
// Cierro todos los handles de los hilos
    
for(i=0i<MAX_THREADSi++)
    {
        
CloseHandle(hThreadArray[i]);
    }
    
printf("Fin de recepcion de mensajes");
    
getchar();
    return (
EXIT_SUCCESS);
}

DWORD WINAPI MyThreadFunctionLPVOID lpParam 

    
HANDLE hStdout;

    
WSADATA wsaData;
    
SOCKET conn_socket,comm_socket;
    
SOCKET comunicacion;
    
struct sockaddr_in server;
    
struct sockaddr_in client;
    
struct hostent *hp;
    
int resp,stsize;
    
char RecvBuff[100];

    
//Inicializamos la DLL de sockets
    
resp=WSAStartup(MAKEWORD(1,0),&wsaData);
    if(
resp){
        
printf("Error al inicializar socket\n");
        
getchar();
        return 
resp;
    }

    
//Obtenemos la IP que usará nuestro servidor...
    // en este caso localhost indica nuestra propia máquina...
    
hp=(struct hostent *)gethostbyname("localhost");

    if(!
hp){
        
printf("No se ha encontrado servidor...\n");
        
getchar();
        
WSACleanup();
        return 
WSAGetLastError();
    }

    
// Creamos el socket...
    
conn_socket=socket(AF_INET,SOCK_STREAM0);
    if(
conn_socket==INVALID_SOCKET) {
        
printf("Error al crear socket\n");
        
getchar();
        
WSACleanup();
        return 
WSAGetLastError();
    }
  
    
memset(&server0sizeof(server)) ;
    
memcpy(&server.sin_addrhp->h_addrhp->h_length);
    
server.sin_family hp->h_addrtype;
    
server.sin_port htons(6000);

    
// Asociamos ip y puerto al socket
    
resp=bind(conn_socket, (struct sockaddr *)&serversizeof(server));
    if(
resp==SOCKET_ERROR){
        
printf("Error al asociar puerto e ip al socket\n");
        
closesocket(conn_socket);
        
WSACleanup();
        
getchar();
        return 
WSAGetLastError();
    }

    if(
listen(conn_socket1)==SOCKET_ERROR){
        
printf("Error al habilitar conexiones entrantes\n");
        
closesocket(conn_socket);
        
WSACleanup();
        
getchar();
        return 
WSAGetLastError();
    }
              
    
// Aceptamos conexiones entrantes
    
printf("Esperando conexiones entrantes... \n");
    
stsize=sizeof(struct sockaddr);
    
comm_socket=accept(conn_socket,(struct sockaddr *)&client,&stsize);
    if(
comm_socket==INVALID_SOCKET){
        
printf("Error al aceptar conexión entrante\n");
        
closesocket(conn_socket);
        
WSACleanup();
        
getchar();
        return 
WSAGetLastError();
    }
    
printf("Conexion entrante desde: %s\n"inet_ntoa(client.sin_addr));
              
    
// Como no vamos a aceptar más conexiones cerramos el socket escucha
    
closesocket(conn_socket);

    
printf("Recibiendo Mensajes... \n");
    
recv (comm_socketRecvBuffsizeof(RecvBuff), 0);
    
printf("Datos recibidos: %s \n"RecvBuff);

    
// Cerramos el socket de la comunicacion
    
closesocket(comm_socket);

    
// Cerramos liberia winsock
    
WSACleanup();
    return 
0
}

void ErrorHandler(char *lpszFunction
{
    
// Retrieve the system error message for the last-error code.

    
LPVOID lpMsgBuf;
    
LPVOID lpDisplayBuf;
    
DWORD dw GetLastError(); 

    
FormatMessage(
        
FORMAT_MESSAGE_ALLOCATE_BUFFER 
        
FORMAT_MESSAGE_FROM_SYSTEM |
        
FORMAT_MESSAGE_IGNORE_INSERTS,
        
NULL,
        
dw,
        
MAKELANGID(LANG_NEUTRALSUBLANG_DEFAULT),
        (
LPTSTR) &lpMsgBuf,
        
0NULL );

    
// Display the error message.

    
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT
        (
lstrlen((LPCTSTRlpMsgBuf) + lstrlen((LPCTSTRlpszFunction) + 40) * sizeof(TCHAR)); 
    
printf("%s failed with error %d: %s",lpszFunctiondwlpMsgBuf);
    
MessageBox(NULL, (LPCTSTRlpDisplayBufTEXT("Error"), MB_OK); 

    
// Free error-handling buffer allocations.

    
LocalFree(lpMsgBuf);
    
LocalFree(lpDisplayBuf);

La idea es que ambos procesos se conecten al servidor y envien la cadena con el pid y el tiempo de ejecucion pero me sale lo siguiente en la consola:

Código:
Esperando conexiones entrantes...
Error al asociar puerto e ip al socket
Conexion entrante desde: 127.0.0.1
Recibiendo Mensajes...
Datos recibidos: El proceso con PID: 3748 ha funcionado durante 500 milisegundos.
Y se queda esperando en:
Código PHP:
WaitForMultipleObjects(MAX_THREADShThreadArrayTRUEINFINITE); 
Si pongo que se cree un solo hilo va bien pero la idea de usar hilos es para que pueda conectar alguno mas jejeje.
¿Me pueden explicar porque me falla y que debo cambiar?

Última edición por aguml fecha: 06-03-2017 a las 12:10:57.
Responder Con Cita
  #2  
Antiguo 06-03-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 12
aguml Va por buen camino
Al final he conseguido que funcione pero quiero aprender a hacer bien las cosas y me gustaria que lo corrigiese alguien y me diga si hago algo mal y me pueda explicar como hacerlo correctamente.
Aquí está el código:
Servidor:
Código PHP:
#include <stdio.h>
#include <windows.h>

#define MAX_THREADS 2

typedef struct DatosServidor {
    
SOCKET conn_socket;
DATOS_SERVIDOR;

DWORD WINAPI MyThreadFunctionLPVOID lpParam );
void ErrorHandler(char *NameFunction);

int main(int argcchar *argv[]){

    
//Necesarias para crear los hilos
    
DWORD   dwThreadIdArray[MAX_THREADS];
    
HANDLE  hThreadArray[MAX_THREADS];
    
int i;

    
//Necesarias para crear el servidor
    
DATOS_SERVIDOR datos;
    
WSADATA wsaData;
    
struct sockaddr_in server;
    
struct hostent *hp;
    
int resp;

    
//Inicializamos la DLL de sockets
    
resp=WSAStartup(MAKEWORD(1,0),&wsaData);
    if(
resp){
        
printf("Error al inicializar socket\n");
        
getchar();
        return 
resp;
    }

    
//Obtenemos la IP que usará nuestro servidor...
    // en este caso localhost indica nuestra propia máquina...
    
hp=(struct hostent *)gethostbyname("localhost");

    if(!
hp){
        
printf("No se ha encontrado servidor...\n");
        
getchar();
        
WSACleanup();
        return 
WSAGetLastError();
    }

    
// Creamos el socket...
    
datos.conn_socket=socket(AF_INET,SOCK_STREAM0);
    if(
datos.conn_socket==INVALID_SOCKET) {
        
printf("Error al crear socket\n");
        
getchar();
        
WSACleanup();
        return 
WSAGetLastError();
    }

    
memset(&server0sizeof(server)) ;
    
memcpy(&server.sin_addrhp->h_addrhp->h_length);
    
server.sin_family hp->h_addrtype;
    
server.sin_port htons(6000);

    
// Asociamos ip y puerto al socket
    
resp=bind(datos.conn_socket, (struct sockaddr *)&serversizeof(server));
    if(
resp==SOCKET_ERROR){
        
printf("Error al asociar puerto e ip al socket\n");
        
closesocket(datos.conn_socket);
        
WSACleanup();
        
getchar();
        return 
WSAGetLastError();
    }

    if(
listen(datos.conn_socket1)==SOCKET_ERROR){
        
printf("Error al habilitar conexiones entrantes\n");
        
closesocket(datos.conn_socket);
        
WSACleanup();
        
getchar();
        return 
WSAGetLastError();
    }

    
printf("Esperando conexiones entrantes... \n");

    for(
i=0i<MAX_THREADSi++ )
    {
        
// Creo el hilo para iniciar la ejecución en su función

        
hThreadArray[i] = CreateThread
            
NULL,                   // default security attributes
            
0,                      // use default stack size  
            
MyThreadFunction,       // thread function name
            
&datos,                 // argument to thread function
            
0,                      // use default creation flags
            
&dwThreadIdArray[i]);   // returns the thread identifier

        // Compruebo el valor de retorno
        // Si CreateThread falla, termino la ejecución
        // Esto limpiará automáticamente los hilos y la memoria

        
if (hThreadArray[i] == NULL
        {
           
ErrorHandler("CreateThread");
           
getchar();
           return 
3;
        }
    } 
// Fin del bucle de creacion de hilos

    // Espero a que terminen todos los hilos
    
WaitForMultipleObjects(MAX_THREADShThreadArrayTRUEINFINITE);

    
// Como no vamos a aceptar más conexiones cerramos el socket escucha
    
closesocket(datos.conn_socket);

    
// Cerramos liberia winsock
    
WSACleanup();

    
// Cierro todos los handles de los hilos
    
for(i=0i<MAX_THREADSi++)
    {
        
CloseHandle(hThreadArray[i]);
    }
    
printf("Fin de recepcion de mensajes");
    
getchar();
    return (
EXIT_SUCCESS);
}

DWORD WINAPI MyThreadFunctionLPVOID lpParam 
{
    
char RecvBuff[100];
    
SOCKET comm_socket;
    
DATOS_SERVIDOR *datos;
    
struct sockaddr_in client;
    
int stsize;

    
datos=(DATOS_SERVIDOR*)lpParam;

    
// Aceptamos conexiones entrantes
    
stsize=sizeof(struct sockaddr);
    
comm_socket=accept(datos->conn_socket,(struct sockaddr *)&client,&stsize);
    if(
comm_socket==INVALID_SOCKET){
        
printf("Error al aceptar conexión entrante\n");
        
getchar();
        return 
WSAGetLastError();
    }
    
printf("Conexion entrante desde: %s\n"inet_ntoa(client.sin_addr));

    
printf("Recibiendo Mensajes... \n");
    
recv (comm_socketRecvBuffsizeof(RecvBuff), 0);
    
printf("Datos recibidos: %s \n"RecvBuff);

    
// Cerramos el socket de la comunicacion
    
closesocket(comm_socket);

    return 
0;
}

void ErrorHandler(char *NameFunction)
{
    
LPVOID lpMsgBuf;
    
DWORD dw GetLastError(); 

    
// Recupero el mensaje de error del sistema para el último error ocurrido
    
FormatMessage(
        
FORMAT_MESSAGE_ALLOCATE_BUFFER 
        
FORMAT_MESSAGE_FROM_SYSTEM |
        
FORMAT_MESSAGE_IGNORE_INSERTS,
        
NULL,
        
dw,
        
MAKELANGID(LANG_NEUTRALSUBLANG_DEFAULT),
        (
LPTSTR) &lpMsgBuf,
        
0NULL );

    
// Muestro el mensaje de error
    
printf("Error: %s failed with error %d: %s",NameFunctiondwlpMsgBuf);

    
// Libero la memoria allocada
    
LocalFree(lpMsgBuf);

Cliente:
Código PHP:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

int main(int argcchar *argv[]){

    
WSADATA wsaData;
    
SOCKET conn_socket;
    
struct sockaddr_in server;
    
struct hostent *hp;
    
int resp,salida;
    
unsigned long inicio,fin,lapso;
    
char SendBuff[100];
    
HWND windowHandle;
    
DWORD processID;

    
//Obtengo el tiempo en el que inicia el proceso
    
inicio=GetTickCount();

    
//Inicializamos la DLL de sockets
    
resp=WSAStartup(MAKEWORD(1,0),&wsaData);
    if(
resp){
        
printf("Error al inicializar socket\n");
        
getchar();
        return -
1;
    }

    
//Obtenemos la IP del servidor... en este caso
    // localhost indica nuestra propia máquina...
    
hp=(struct hostent *)gethostbyname("localhost");

    if(!
hp){
        
printf("No se ha encontrado servidor...\n");
        
getchar();
        
WSACleanup();
        return 
WSAGetLastError();
    }

    
// Creamos el socket...
    
conn_socket=socket(AF_INET,SOCK_STREAM0);
    if(
conn_socket==INVALID_SOCKET) {
        
printf("Error al crear socket\n");
        
getchar();
        
WSACleanup();
        return 
WSAGetLastError();
    }

    
memset(&server0sizeof(server)) ;
    
memcpy(&server.sin_addrhp->h_addrhp->h_length);
    
server.sin_family hp->h_addrtype;
    
server.sin_port htons(6000);

    
// Nos conectamos con el servidor...
    
if(connect(conn_socket,(struct sockaddr *)&server,sizeof(server))==SOCKET_ERROR){
        
printf("Fallo al conectarse con el servidor\n");
        
closesocket(conn_socket);
        
WSACleanup();
        
getchar();
        return 
WSAGetLastError();
    }
    
printf("Conexion establecida con: %s\n"inet_ntoa(server.sin_addr));

    
//Esto lo pongo para tener una salida del proceso aleatoria
    //No es necesaria para nada pero al menos asi consigo simular
    //que el proceso hace algo mas a parte de comunicarse
    
srand(time(NULL));
    do{
        
salida rand()%1000;
        
Sleep(10);
    }while(
salida != 0);

    
//Obtengo el tiempo en que termina el proceso
    
fin=GetTickCount();

    
//Obtengo el lapso de tiempo transcurrido
    
lapso=fin-inicio;

    
processID GetCurrentProcessId();

    
//Enviamos el lapso de tiempo que transcurrio...
    
printf("Enviando lapso de tiempo... \n");
    
sprintf(SendBuff,"El proceso con PID: %lu ha funcionado durante %lu milisegundos.",processID,lapso);
    
send(conn_socket,SendBuff,sizeof(SendBuff),0);
    
printf("Lapso enviado: %lu milisegundos\n"lapso);

    
// Cerramos el socket y liberamos la DLL de sockets
    
closesocket(conn_socket);
    
WSACleanup();
    
getchar();
    return 
EXIT_SUCCESS;

Gracias de antemano
Responder Con Cita
  #3  
Antiguo 06-03-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.198
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Tu hilo contiene todo el servidor con lo que se repiten y ten en cuenta que no puedes tener dos servidores escuchando por el mismo puerto, el segundo sencillamente falla. El hilo debe crearse tras accept y el parámetro que pasas el el socket que devuelve accept. Cuando la comunicación con ese cliente termine, el hilo debe hacerlo también, con lo que tendrás que detectar un error de lectura recv < 0 y un posible comando de desconexión que diseñas tu mismo y que al cecibirlo desconectas el socket y terminas el hilo saliendo de su bucle.

WaitForMultipleObjects espera a que un hilo o todos terminen. Se utiliza para control. En este caso puedes establecer un número máximo de hilos de ejecución y mantener al servidor esperando antes de crear otra conexión en un nuevo hilo.

Saludos.
Responder Con Cita
  #4  
Antiguo 06-03-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 12
aguml Va por buen camino
La verdad es que lo único que creo entender es lo que me dices de accept el cual puse dentro del hilo porque pensé que era bloqueante pero si no es así es tan simple como ponerlo en el bucle for antes de llamar al hilo y pasar el valor retornado en vez del que paso ¿no?
Lo demás no entiendo lo que me quieres decir. Si pudieras corregirme el código y poner comentarios en las partes que modifiques explicando el porque lo entendería mejor.
Responder Con Cita
  #5  
Antiguo 06-03-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.198
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Te muestro unos cambios en el servidor y en el cliente. En el server he eliminado el tratamiento de hilos para no enturbiar el código y muestro donde debería haber un bucle para mantenerse activo hasta orden contraria. También muestro como crea un hilo cada vez que acepta un cliente. Efectivamente accept es bloqueante, solo se libera al aceptar un cliente, es por ese motivo por el que no se coloca en el thread.

El server no necesita especificar ninguna dirección, por eso se usa INADDR_ANY. Tambien te muestro una forma más amable de inicializar la dirección tanto en el servidor como en el cliente. Me he tomado la libertad de cambiar algún nombre de variable y de eliminar la estructura parámetro de los hilos, puesto que pasando el Socket de comunicación basta.

Código PHP:
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>

DWORD WINAPI ThClient(SOCKET *Sock)
{
  
int Len=0;
  
char RecvBuff[100];

  
// Encontrando la dirección IP (se podría pasar como parámetro...)
  
struct sockaddr_in client;
  
int addr_size sizeof(sockaddr_in);
  
getpeername(*Sock, (sockaddr*)&client, &addr_size);

  
printf("Conexion entrante desde: %s\n"inet_ntoa(client.sin_addr));
  
printf("Recibiendo Mensajes... \n");
  do{
    
// Leemos los datos entrantes
    
Len recv(*SockRecvBuffsizeof(RecvBuff), 0); //recibimos los datos que envie
    
if(Len<0) continue;
    
printf("Datos recibidos: %s \n"RecvBuff);
    
// Un comando debería servir para salir del bucle.
    
if(!strnicmp(RecvBuff"Adios"5)) break;
    
// Si tenemos datos hablamos...
    
gets(RecvBuff);
    
strcat(RecvBuff"\n");
    
send(*SockRecvBufflstrlen(RecvBuff)+10);
  } while(
Len && Len!=-1);

  
closesocket(*Sock);

  return 
0;
}

int main(int argcchar *argv[])
{
  
//Necesarias para crear el servidor
  
WSADATA wsaData;
  
SOCKET Sock_e;   // Sock de escucha
  
SOCKET Sock_c;   // Sock de comunicación
  
struct sockaddr_in serverclient;
  
struct hostent *host;
  
DWORD Port 6000;
  
int resp;

  
//Inicializamos la DLL de sockets
  
resp WSAStartup(MAKEWORD(1,0),&wsaData);
  if(
resp){
    
printf("Error al inicializar socket\n");
    
getchar();
    return 
resp;
  }

  
//Obtenemos la IP que usará nuestro servidor...
  // en este caso localhost indica nuestra propia máquina...
  
host = (struct hostent *)gethostbyname("localhost");

  if(!
host){
    
printf("No se ha encontrado servidor...\n");
    
getchar();
    
WSACleanup();
    return 
WSAGetLastError();
  }

  
// Creamos el socket...
  
Sock_e socket(AF_INETSOCK_STREAMIPPROTO_TCP);
  if(
Sock_e == INVALID_SOCKET) {
    
printf("Error al crear socket\n");
    
getchar();
    
WSACleanup();
    return 
WSAGetLastError();
  }

//  memset(&server, 0, sizeof(server)) ;
//  memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
//  server.sin_family = hp->h_addrtype;
//  server.sin_port = htons(6000);

  
server.sin_family AF_INET;
  
server.sin_addr.s_addr INADDR_ANY;
  
server.sin_port htons(Port);

  
// Asociamos ip y puerto al socket
  
resp bind(Sock_e, (struct sockaddr *)&serversizeof(server));
  if(
resp == SOCKET_ERROR){
     
printf("Error al asociar puerto e ip al socket\n");
     
closesocket(Sock_e);
     
WSACleanup();
     
getchar();
     return 
WSAGetLastError();
  }

  
// bucle de escucha
  
while(true){
     
// Escuchando puerto
     
printf("\nEscuchando por el puerto %d\n"Port);

     if(
listen(Sock_e1) == SOCKET_ERROR){
       
printf("Error al habilitar conexiones entrantes\n");
       
closesocket(Sock_e);
       
WSACleanup();
       
getchar();
       return 
WSAGetLastError();
     }
     else{
       
printf("Esperando conexiones entrantes... \n");
       
resp sizeof(sockaddr);
       
Sock_c accept(Sock_e,(sockaddr*)&client, &resp);
       
// Creamos el hilo
       
CloseHandle(CreateThread(NULL0,  (LPTHREAD_START_ROUTINE)ThClient, &Sock_c0,0));
     }
  } 
// Fin del bucle de escucha

  // Como no vamos a aceptar más conexiones cerramos el socket escucha
  
closesocket(Sock_c);

  
// Cerramos liberia winsock
  
WSACleanup();
  
printf("Fin de recepcion de mensajes");
  
getchar();
  return (
EXIT_SUCCESS);

El cliente también lo he cambiado un poco, sobre todo para indicarte donde deberías poner bucles. En principio serían dos bucles, uno principal que trataría de conectarse contínuamente al server, aunque éste no exista. De este bucle se saldría por actuación del usuario cerrando la app con un comando a tal fin.

Un segundo bucle mantendría la conversación con el hilo que el server nos cree hasta que la finalicemos con algún comando desde el teclado, por ejemplo y enviado al servidor. El server al recibir ese comando saldría del bucle del thread y finalizaría dicho hilo.

Código PHP:
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argcchar *argv[])
{
  
WSADATA wsaData;
  
SOCKET conn_socket;
  
struct sockaddr_in server;
  
struct hostent *host;
  
DWORD Port 6000;
  
int respsalida;
  
unsigned long inicio,fin,lapso;
  
char SendBuff[100];
  
HWND windowHandle;
  
DWORD processID;

  
//Obtengo el tiempo en el que inicia el proceso
  
inicio GetTickCount();

  
//Inicializamos la DLL de sockets
  
resp=WSAStartup(MAKEWORD(1,0),&wsaData);
  if(
resp){
    
printf("Error al inicializar socket\n");
    
getchar();
    return -
1;
  }


  
// Aquí debería empezar el Bucle cliente principal
  // Para que no cierre aunque no conecte con el server. Solo cerraría por mediación del usuario
  // Saliendo del bucle.

  // Creamos el socket...
  
conn_socket socket(AF_INETSOCK_STREAMIPPROTO_TCP);
  if(
conn_socket == INVALID_SOCKET) {
    
printf("Error al crear socket\n");
    
getchar();
    
WSACleanup();
    return 
WSAGetLastError();
  }

/*
  memset(&server, 0, sizeof(server)) ;
  memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
  server.sin_family = hp->h_addrtype;
  server.sin_port = htons(Port);
*/

  //Dirección IP del servidor y Puerto
  // localhost indica nuestra propia máquina...
  
host = (struct hostent *)gethostbyname("localhost");
  if(!
host){
     
printf("No se ha encontrado servidor...\n");
     
getchar();
     
WSACleanup();
     return 
WSAGetLastError();
  }
  
server.sin_family AF_INET;
  
server.sin_port   htons(Port);
  
server.sin_addr   = *((struct in_addr *)host->h_addr);
  
ZeroMemory(server.sin_zero8);

  
// Nos conectamos con el servidor...
  
if(connect(conn_socket, (struct sockaddr *)&server,sizeof(server)) == SOCKET_ERROR){
    
printf("Fallo al conectarse con el servidor\n");
    
closesocket(conn_socket);
    
WSACleanup();
    
getchar();
    return 
WSAGetLastError();
  }

  
// Aquí debería empezar un bucle de comunicación con el servidor según tu propio protocolo

  
printf("Conexion establecida con: %s\n"inet_ntoa(server.sin_addr));
  
//Esto lo pongo para tener una salida del proceso aleatoria
  //No es necesaria para nada pero al menos asi consigo simular
  //que el proceso hace algo mas a parte de comunicarse
  
srand(time(NULL));
  do{
    
salida rand()%1000;
    
Sleep(10);
  }while(
salida != 0);

   
//Obtengo el tiempo en que termina el proceso
  
fin GetTickCount();

  
//Obtengo el lapso de tiempo transcurrido
  
lapso fin-inicio;
  
processID GetCurrentProcessId();

  
//Enviamos el lapso de tiempo que transcurrio...
  
printf("Enviando lapso de tiempo... \n");
  
sprintf(SendBuff,"El proceso con PID: %lu ha funcionado durante %lu milisegundos.",processID,lapso);
  
send(conn_socket,SendBuff,sizeof(SendBuff),0);
  
printf("Lapso enviado: %lu milisegundos\n"lapso);

  
// Cerramos el socket y liberamos la DLL de sockets
  
closesocket(conn_socket);
  
WSACleanup();
  
getchar();
  return 
EXIT_SUCCESS;

Esto está muy en pañales pero funciona. Ahora deberás diseñar tus bucles para que la funcionalidad sea la que buscas, y una colección de palabras clave o comandos que se intercambiarán el servidor con cada cliente. Por su puesto, cada palabra clave, significará una acción a llevar a cabo o un indicativo del dato que estamos pasando. Para eso te debes inventar una sintaxis.

Espero que entiendas un poco mejor el tema.

Saludos.
Responder Con Cita
  #6  
Antiguo 07-03-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 12
aguml Va por buen camino
Ahora si entiendo mejor. En realidad tú código es más de lo que necesito creo yo. Realmente la idea es que un cliente se conecte al servidor y luego obtenga el tiempo inicial y cuando se vaya a salir del proceso calcule el lapso de tiempo transcurrido y lo envie al servidor, no necesita ni enviar más nada ni recibir por lo que el servidor tampoco necesita esperar más nada después de recibir el valor ya que sabe que después de eso el cliente se cerrará. No se si me entiendes, no habrá más comunicación con ese cliente y este se cerrará si o si.
Lo que no veo en tu código del server es como sales del bucle infinito que pusiste para los hilos ya que no veo ningún break. En mi caso tenia que especificar el número de hilos para que WaitForMultipleObjects supiese cuando terminar y tu no lo usas por lo que jamás se saldría a no ser que cierre el programa servidor. Nunca se ejecutaría lo que está después del bucle y no veo la manera de conseguirlo sin hacer lo que yo hice de indicar el número de hilos a WaitForMultipleObjects.
Responder Con Cita
  #7  
Antiguo 07-03-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 12
aguml Va por buen camino
Ahora mismo lo tengo asi y sigo teniendo algunas dudas sobre todo en como colocar el bucle del cliente ya que hice algo que creo que no es del todo correcto pero no se seguro. Ademas he colocado un comentario en la zona donde se asignan los parametros para el server en el codigo del cliente que me gustaria que me pudieses solventar.
Aqui el codigo del servidor:
Código PHP:
#include <stdio.h>
#include <string.h>
#include <windows.h>

#define MAX_THREADS 2

DWORD WINAPI ThClient(SOCKET *Sock);
void ErrorHandler(char *NameFunction);

int main(int argcchar *argv[]){

    
//Necesarias para crear los hilos
    
DWORD   dwThreadIdArray[MAX_THREADS];
    
HANDLE  hThreadArray[MAX_THREADS];
    
int i;

    
//Necesarias para crear el servidor
    
WSADATA wsaData;
    
struct sockaddr_in server,client;
    
struct hostent *hp;
    
int resp;
    
SOCKET Sock_c;  //Socket del cliente
    
SOCKET Sock_e;  //Socket de escucha del servidor
    
DWORD Port=6000;
    
int stsize;

    
//Inicializamos la DLL de sockets
    
resp=WSAStartup(MAKEWORD(1,0),&wsaData);
    if(
resp){
        
printf("Error al inicializar socket\n");
        
getchar();
        return 
resp;
    }

    
//Obtenemos la IP que usará nuestro servidor...
    // en este caso localhost indica nuestra propia máquina...
    
hp=(struct hostent *)gethostbyname("localhost");

    if(!
hp){
        
printf("No se ha encontrado servidor...\n");
        
getchar();
        
WSACleanup();
        return 
WSAGetLastError();
    }

    
// Creamos el socket...
    
Sock_e=socket(AF_INET,SOCK_STREAM0);
    if(
Sock_e==INVALID_SOCKET) {
        
printf("Error al crear socket\n");
        
getchar();
        
WSACleanup();
        return 
WSAGetLastError();
    }

    
memset(&server0sizeof(server)) ;
    
server.sin_family AF_INET;
    
server.sin_addr.s_addr INADDR_ANY;
    
server.sin_port htons(Port);

    
// Asociamos ip y puerto al socket
    
resp=bind(Sock_e, (struct sockaddr *)&serversizeof(server));
    if(
resp==SOCKET_ERROR){
        
printf("Error al asociar puerto e ip al socket\n");
        
closesocket(Sock_e);
        
WSACleanup();
        
getchar();
        return 
WSAGetLastError();
    }

    if(
listen(Sock_e1)==SOCKET_ERROR){
        
printf("Error al habilitar conexiones entrantes\n");
        
closesocket(Sock_e);
        
WSACleanup();
        
getchar();
        return 
WSAGetLastError();
    }

    
printf("Esperando conexiones entrantes... \n");

    for(
i=0i<MAX_THREADSi++ )
    {
        
// Aceptamos conexiones entrantes
        
stsize=sizeof(struct sockaddr);
        
Sock_c=accept(Sock_e,(struct sockaddr *)&client,&stsize);
        if(
Sock_c==INVALID_SOCKET){
            
printf("Error al aceptar conexión entrante\n");
            
getchar();
            return 
WSAGetLastError();
        }
        
//printf("Conexion entrante desde: %s\n", inet_ntoa(client.sin_addr));

        // Creo el hilo para iniciar la ejecución en su función
        
hThreadArray[i] = CreateThread
            
NULL,                              // default security attributes
            
0,                                 // use default stack size
            
(LPTHREAD_START_ROUTINE)ThClient,  // thread function name
            
&Sock_c,                      // argument to thread function
            
0,                                 // use default creation flags
            
&dwThreadIdArray[i]);              // returns the thread identifier

        // Compruebo el valor de retorno
        // Si CreateThread falla, termino la ejecución
        // Esto limpiará automáticamente los hilos y la memoria

        
if (hThreadArray[i] == NULL
        {
           
ErrorHandler("CreateThread");
           
getchar();
           return 
3;
        }
    } 
// Fin del bucle de creacion de hilos

    // Espero a que terminen todos los hilos
    
WaitForMultipleObjects(MAX_THREADShThreadArrayTRUEINFINITE);

    
// Como no vamos a aceptar más conexiones cerramos el socket escucha
    
closesocket(Sock_e);

    
// Cerramos liberia winsock
    
WSACleanup();

    
// Cierro todos los handles de los hilos
    
for(i=0i<MAX_THREADSi++)
    {
        
CloseHandle(hThreadArray[i]);
    }
    
printf("Fin de recepcion de mensajes");
    
getchar();
    return (
EXIT_SUCCESS);
}

DWORD WINAPI ThClient(SOCKET *Sock)
{
    
char RecvBuff[100];

    
memset(RecvBuff,0,sizeof(RecvBuff));
    
recv (*SockRecvBuffsizeof(RecvBuff), 0);

    if(
strlen(RecvBuff)==0)
        
printf("El cliente se ha cerrado antes de enviar los datos\n");
    else
        
printf("%s\n"RecvBuff);

    
memset(RecvBuff,0,sizeof(RecvBuff));
    
recv (*SockRecvBuffsizeof(RecvBuff), 0);

    if(
strlen(RecvBuff)==0)
        
printf("El cliente se ha cerrado antes de enviar los datos\n");
    else
        
printf("Datos recibidos: %s \n"RecvBuff);

    
// Cerramos el socket de la comunicacion
    
closesocket(*Sock);

    return 
0;
}

void ErrorHandler(char *NameFunction)
{
    
LPVOID lpMsgBuf;
    
DWORD dw GetLastError(); 

    
// Recupero el mensaje de error del sistema para el último error ocurrido
    
FormatMessage(
        
FORMAT_MESSAGE_ALLOCATE_BUFFER |
        
FORMAT_MESSAGE_FROM_SYSTEM |
        
FORMAT_MESSAGE_IGNORE_INSERTS,
        
NULL,
        
dw,
        
MAKELANGID(LANG_NEUTRALSUBLANG_DEFAULT),
        (
LPTSTR) &lpMsgBuf,
        
0NULL );

    
// Muestro el mensaje de error
    
printf("Error: %s failed with error %d: %s",NameFunctiondwlpMsgBuf);

    
// Libero la memoria allocada
    
LocalFree(lpMsgBuf);

Aqui el codigo del cliente:
Código PHP:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

int main(int argcchar *argv[]){

    
WSADATA wsaData;
    
SOCKET conn_socket;
    
struct sockaddr_in server;
    
struct hostent *host;
    
DWORD Port 6000;
    
int resp,salida;
    
unsigned long inicio,fin,lapso;
    
char SendBuff[100];
    
HWND windowHandle;
    
DWORD processID;

    
//Inicializamos la DLL de sockets
    
resp=WSAStartup(MAKEWORD(1,0),&wsaData);
    if(
resp){
        
printf("Error al inicializar socket\n");
        
getchar();
        return -
1;
    }

    
//Obtenemos la IP del servidor... en este caso
    // localhost indica nuestra propia máquina...
    
host=(struct hostent *)gethostbyname("localhost");

    if(!
host){
        
printf("No se ha encontrado servidor...\n");
        
getchar();
        
WSACleanup();
        return 
WSAGetLastError();
    }

    
// Creamos el socket...
    
conn_socket=socket(AF_INET,SOCK_STREAM0);
    if(
conn_socket==INVALID_SOCKET) {
        
printf("Error al crear socket\n");
        
getchar();
        
WSACleanup();
        return 
WSAGetLastError();
    }

    
memset(&server0sizeof(server)) ;
    
server.sin_family AF_INET;
    
server.sin_port   htons(Port);
    
//La siguiente linea, si no fuesen cliente y servidor en el mismo equipo
    //¿Tendria que darle la direccion ip del servidor?
    //Es que ahora mismo apunta a localhost del cliente ¿no?
    
server.sin_addr   = *((struct in_addr *)host->h_addr);

    
// Nos conectamos con el servidor...
    
printf("Conectando con el servidor\n");
    while(
connect(conn_socket,(struct sockaddr *)&server,sizeof(server))==SOCKET_ERROR)
        
Sleep(10);

    
processID GetCurrentProcessId();
    
printf("Conexion establecida con: %s con proceso con PID %lu\n"inet_ntoa(server.sin_addr),processID);
    
sprintf(SendBuff,"Conexion establecida con: %s con proceso con PID: %lu.",inet_ntoa(*((struct in_addr *)host->h_addr)),processID);
    
send(conn_socket,SendBuff,sizeof(SendBuff),0);

    
//Obtengo el tiempo en el que inicia el proceso
    
inicio=GetTickCount();

    
//Esto lo pongo para tener una salida del proceso aleatoria
    //No es necesaria para nada pero al menos asi consigo simular
    //que el proceso hace algo mas a parte de comunicarse
    
srand(time(NULL));
    do{
        
salida rand()%1000;
        
Sleep(10);
    }while(
salida != 0);

    
//Obtengo el tiempo en que termina el proceso
    
fin=GetTickCount();

    
//Obtengo el lapso de tiempo transcurrido
    
lapso=fin-inicio;

    
//Enviamos el lapso de tiempo que transcurrio...
    
printf("Enviando lapso de tiempo... \n");
    
sprintf(SendBuff,"El proceso con PID: %lu ha funcionado durante %lu milisegundos.",processID,lapso);
    
send(conn_socket,SendBuff,sizeof(SendBuff),0);
    
printf("Lapso enviado: %lu milisegundos\n"lapso);

    
// Cerramos el socket y liberamos la DLL de sockets
    
closesocket(conn_socket);
    
WSACleanup();
    
getchar();
    return 
EXIT_SUCCESS;

Responder Con Cita
  #8  
Antiguo 07-03-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.198
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Para que el cliente no termine si no conecta con el servidor y continúe intentando la conexión, debe contener un bucle y quedaría algo como esto:
Código PHP:
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argcchar *argv[]){
  
WSADATA wsaData;
  
SOCKET conn_socket;
  
struct sockaddr_in server;
  
struct hostent *host;
  
char ServerAdr[] = "localhost";   // Nombre de la Máquina del Server
  
DWORD Port 6000;
  
int respsalida;
  
unsigned long inicio,fin,lapso;
  
char SendBuff[100];
  
HWND windowHandle;
  
DWORD processID;
  
BOOL Salir false;
  
int Result EXIT_SUCCESS;

  
//Obtengo el tiempo en el que inicia el proceso
  
inicio GetTickCount();

  
//Inicializamos la DLL de sockets
  
resp WSAStartup(MAKEWORD(1,0),&wsaData);
  if(
resp){
    
printf("Error al inicializar socket\n");
    
getchar();
    return -
1;
  }

  
// Bucle cliente principal
  
while(!Salir){
    
// Creamos el socket...
    
conn_socket socket(AF_INETSOCK_STREAMIPPROTO_TCP);
    if(
conn_socket == INVALID_SOCKET) {
      
printf("Error al crear socket\n");
      
Result WSAGetLastError();
      break;
    }
    else{
      
//Dirección IP del servidor y Puerto
      // localhost indica nuestra propia máquina...
      
host = (struct hostent *)gethostbyname(ServerAdr);
      if(!
host){
        
printf("No se ha encontrado servidor...\n");
        
Result WSAGetLastError();
        break;
      }
      else{
        
server.sin_family AF_INET;
        
server.sin_port   htons(Port);
        
server.sin_addr   = *((struct in_addr *)host->h_addr);
        
ZeroMemory(server.sin_zero8);

        
// Nos conectamos con el servidor...
        
if(connect(conn_socket, (struct sockaddr *)&server,sizeof(server)) == SOCKET_ERROR)
          
printf("Fallo al conectarse con el servidor\n");
        else{
          
// Aquí debería empezar un bucle de comunicación con el servidor según tu propio protocolo
          
printf("Conexion establecida con: %s\n"inet_ntoa(server.sin_addr));
          
//Esto lo pongo para tener una salida del proceso aleatoria
          //No es necesaria para nada pero al menos asi consigo simular
          //que el proceso hace algo mas a parte de comunicarse
          
srand(time(NULL));
          do{
            
salida rand()%1000;
            
Sleep(10);
          }while(
salida != 0);

          
//Obtengo el tiempo en que termina el proceso
          
fin GetTickCount();

          
//Obtengo el lapso de tiempo transcurrido
          
lapso fin-inicio;
          
processID GetCurrentProcessId();

          
//Enviamos el lapso de tiempo que transcurrio...
          
printf("Enviando lapso de tiempo... \n");
          
sprintf(SendBuff,"El proceso con PID: %lu ha funcionado durante %lu milisegundos.",processID,lapso);
          
send(conn_socket,SendBuff,sizeof(SendBuff),0);
          
printf("Lapso enviado: %lu milisegundos\n"lapso);
          
Salir true;
          
// Cerramos el socket y liberamos la DLL de sockets
          
closesocket(conn_socket);
        }
// conect
      
}// host
    
}// socket
  
}//while
  
WSACleanup();
  
getchar();
  return 
Result;

Se pueden simplificar esos mensajes y salidas de error.

Saludos.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Reproductor de Musica Uso de WM_COPYDATA Arieloi2 API de Windows 1 28-05-2010 03:19:19
duda sobre dll romanuel C++ Builder 5 26-02-2008 20:58:52
Una duda sobre ADO PTW Conexión con bases de datos 1 13-04-2004 23:33:14
Duda sobre BDE vs IBX ESA Firebird e Interbase 3 04-03-2004 17:20:07
Duda sobre ADO Omar Alejandro Conexión con bases de datos 7 31-05-2003 19:52:58


La franja horaria es GMT +2. Ahora son las 23:11:24.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi