Ver Mensaje Individual
  #13  
Antiguo 06-03-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Reputación: 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