Club Delphi  
    Paypal   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 05-03-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 14
aguml Va por buen camino
Muy interesante ¿y que hay que cambiar para que la ventana no sea invisible?
Otra cosa, si quisiera enviar el mensaje a otra ventana ¿solo necesito el handle de esa ventana?
Me interesa mucho lo que dices de sockets a bajo nivel ¿no tienes ningún texto donde se explique con ejemplos y cosas así?
Y sobre lo de la memoria compartida tengo mucha curiosidad de ver como se hace eso porque no tengo ni idea.
Responder Con Cita
  #2  
Antiguo 05-03-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.211
Poder: 22
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por aguml Ver Mensaje
Muy interesante ¿y que hay que cambiar para que la ventana no sea invisible?
Estudia la API CreateWindow y los estilos: window styles.

Cita:
Empezado por aguml Ver Mensaje
Otra cosa, si quisiera enviar el mensaje a otra ventana ¿solo necesito el handle de esa ventana?
Si, y que la ventana receptora trate el mensaje WM_COPYDATA

Cita:
Empezado por aguml Ver Mensaje
Me interesa mucho lo que dices de sockets a bajo nivel ¿no tienes ningún texto donde se explique con ejemplos y cosas así?
Winsock Functions y recuerda este hilo donde te puse este ejemplo.

Cita:
Empezado por aguml Ver Mensaje
Y sobre lo de la memoria compartida tengo mucha curiosidad de ver como se hace eso porque no tengo ni idea.
En el hilo que mencioné antes ya te di un enlace sobre los archivos de memoria compartida, aunque en la actualidad está roto. Aquí lo tienes en C++.


Saludos.

Última edición por escafandra fecha: 05-03-2017 a las 13:00:22.
Responder Con Cita
  #3  
Antiguo 05-03-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 14
aguml Va por buen camino
Muchas gracias por toda la información. Sobre sockets en Windows encontré esto: http://www.programacionenc.net/index.php?option=com_content&view=article&id=73:sockets-en-windows&catid=37rogramacion-cc&Itemid=55
Tengo algunas dudas sobre el ejemplo que pones de sockets:
- Por lo que he leído accept espera a que se conecte un cliente pero, si son por ejemplo 2 clientes ¿como seria?
- Si cliente y servidor están en la misma máquina ¿se usaría AF_UNIX? Eso es lo que entendí.
- ¿Cómo sería para que fuesen a sincrónicos?
Responder Con Cita
  #4  
Antiguo 05-03-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.211
Poder: 22
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por aguml Ver Mensaje
Tengo algunas dudas sobre el ejemplo que pones de sockets:
- Por lo que he leído accept espera a que se conecte un cliente pero, si son por ejemplo 2 clientes ¿como seria?
La función accept devuelve un socket de comunicación que usaremos para comunicarnos con ese cliente. para poder aceptar otro cliente debemos volver a ejecutar accept, para que esto ocurra y podamos trabajar con varios clientes, se usan hilos de forma que se crea un hilo nuevo por cada cliente aceptado, cada hilo usará el socket proporcionado por accept

Cita:
Empezado por aguml Ver Mensaje
- Si cliente y servidor están en la misma máquina ¿se usaría AF_UNIX? Eso es lo que entendí.
Puedes usar siempre AF_INET, lo importante es si usarás un protocolo TCP (SOCK_STREAM) o UDP (SOCK_DGRAM) revisa la forma de crear un socket.

Cita:
Empezado por aguml Ver Mensaje
- ¿Cómo sería para que fuesen a sincrónicos?
Para establecer al socket como no bloqueante se usa la función ioctlsocket
También puedes usar un tipo bloqueante con un TimeOut con la función select


Saludos.
Responder Con Cita
  #5  
Antiguo 06-03-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 14
aguml Va por buen camino
Ok muchas gracias. Voy a leer y a probar y ya cuento como me fue.
Responder Con Cita
  #6  
Antiguo 06-03-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 14
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 MyThreadFunction( LPVOID lpParam );
void ErrorHandler(LPTSTR lpszFunction);

int main(int argc, char *argv[]){

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

    for(
i=0; i<MAX_THREADS; i++ )
    {
        
// 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_THREADS, hThreadArray, TRUE, INFINITE);

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

DWORD WINAPI MyThreadFunction( LPVOID 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_STREAM, 0);
    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(6000);

    
// Asociamos ip y puerto al socket
    
resp=bind(conn_socket, (struct sockaddr *)&server, sizeof(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_socket, 1)==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_socket, RecvBuff, sizeof(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_NEUTRAL, SUBLANG_DEFAULT),
        (
LPTSTR) &lpMsgBuf,
        
0, NULL );

    
// Display the error message.

    
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
        (
lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR)); 
    
printf("%s failed with error %d: %s",lpszFunction, dw, lpMsgBuf);
    
MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("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_THREADS, hThreadArray, TRUE, INFINITE); 
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 13:10:57.
Responder Con Cita
  #7  
Antiguo 06-03-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 14
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 MyThreadFunction( LPVOID lpParam );
void ErrorHandler(char *NameFunction);

int main(int argc, char *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_STREAM, 0);
    if(
datos.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(6000);

    
// Asociamos ip y puerto al socket
    
resp=bind(datos.conn_socket, (struct sockaddr *)&server, sizeof(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_socket, 1)==SOCKET_ERROR){
        
printf("Error al habilitar conexiones entrantes\n");
        
closesocket(datos.conn_socket);
        
WSACleanup();
        
getchar();
        return 
WSAGetLastError();
    }

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

    for(
i=0; i<MAX_THREADS; i++ )
    {
        
// 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_THREADS, hThreadArray, TRUE, INFINITE);

    
// 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=0; i<MAX_THREADS; i++)
    {
        
CloseHandle(hThreadArray[i]);
    }
    
printf("Fin de recepcion de mensajes");
    
getchar();
    return (
EXIT_SUCCESS);
}

DWORD WINAPI MyThreadFunction( LPVOID 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_socket, RecvBuff, sizeof(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_NEUTRAL, SUBLANG_DEFAULT),
        (
LPTSTR) &lpMsgBuf,
        
0, NULL );

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

    
// Libero la memoria allocada
    
LocalFree(lpMsgBuf);
} 
Cliente:
Código PHP:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

int main(int argc, char *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_STREAM, 0);
    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(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
  #8  
Antiguo 06-03-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.211
Poder: 22
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
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 04:19:19
duda sobre dll romanuel C++ Builder 5 26-02-2008 21:58:52
Una duda sobre ADO PTW Conexión con bases de datos 1 14-04-2004 00:33:14
Duda sobre BDE vs IBX ESA Firebird e Interbase 3 04-03-2004 18:20:07
Duda sobre ADO Omar Alejandro Conexión con bases de datos 7 31-05-2003 20:52:58


La franja horaria es GMT +2. Ahora son las 15:01:54.


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