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(*Sock, RecvBuff, sizeof(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(*Sock, RecvBuff, lstrlen(RecvBuff)+1, 0);
} while(Len && Len!=-1);
closesocket(*Sock);
return 0;
}
int main(int argc, char *argv[])
{
//Necesarias para crear el servidor
WSADATA wsaData;
SOCKET Sock_e; // Sock de escucha
SOCKET Sock_c; // Sock de comunicación
struct sockaddr_in server, client;
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_INET, SOCK_STREAM, IPPROTO_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 *)&server, sizeof(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_e, 1) == 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(NULL, 0, (LPTHREAD_START_ROUTINE)ThClient, &Sock_c, 0,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 argc, char *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;
//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_INET, SOCK_STREAM, IPPROTO_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_zero, 8);
// 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.