MULTIMEDIA, Video digital, Grabación, Diseño gráfico, Diseño web, Programación > Webmasters - Diseño Web - Programación - Diseño gráfico

Ayuda por favor!

<< < (2/2)

ALP:
Hola de nuevo, he estado haciendo un prueba de sockets.

No he hecho la prueba con el puerto paralelo, ya que no tengo nada para poder conectarle. Así que lo he preparado con una ventana de edición. Todo lo que teclees en la ventana de edición se enviará a los clientes que estén conectados.
El tema del puerto paralelo, es similar, sólo tienes que crear un hilo que esté continuamente leyendo el puerto ( con ReadFile() ), y todo lo que recibas lo envías a los clientes. Debes hacerlo en un hilo, ya que si no hay nada que leer, el programa se queda esperando en ReadFile(), y no responderá a los mensajes del sistema. Con el hilo, el bucle de mensajes va por un lado, la función que acepta conexiones por otro, y la función de lectura del puerto por otro. Así, todo funcionará sin problemas.

Te pongo también un cliente, que se conecta a este servidor. Los dos están hechos en C. Respecto al Java, no tengo el compilador instalado, pero la gestión de sockets es muy fácil. Los he probado con Dev-C++ (debes incluir la librería libws2_32.lib)


Este es el código del servidor:

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

#define MAX_CLIENT 10  /* número máximo de clientes */
#define PUERTO_SERVIDOR 13527 /* puerto que "escucha" el programa */


HWND hWndEdit;
HANDLE hilo_socket;
SOCKET sock_server;
HINSTANCE hInstApp;
LRESULT CALLBACK (*old_fn_edit)(HWND, UINT, WPARAM, LPARAM);

SOCKET sock_client[MAX_CLIENT];

char *szClassName = "prueba_socket_server";

LRESULT CALLBACK WndMainProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK GestWndEdit (HWND, UINT, WPARAM, LPARAM);
DWORD SocketServidor(LPVOID);


/*---------------------------------------------------------------------------*/
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst,
                    LPSTR lpszArgument,  int nCmdShow)
{
    int i;
    HWND hwnd;
    MSG msg;  
    WNDCLASSEX wincl = {0};
   
DWORD idHilo;
    WSADATA wsadat;
    WORD version = MAKEWORD(1,1);

    /* inicializamos el entorno de windows sockets */
    if (WSAStartup( version, &wsadat)) {
    MessageBox(NULL, "Error inicializando windows sockets", "WSAStartup()", MB_ICONSTOP);
    return 1;
    }

    /* inicializamos el array de clientes */
    ZeroMemory(sock_client, sizeof(SOCKET)*MAX_CLIENT);

    hInstApp = hInst;

    wincl.hInstance = hInst;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WndMainProc;
    wincl.style = CS_HREDRAW|CS_VREDRAW;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wincl))
        return 1;

    hwnd = CreateWindowEx (0, szClassName, "Servidor - sockets", WS_OVERLAPPEDWINDOW,
           CW_USEDEFAULT, CW_USEDEFAULT, 200, 200, HWND_DESKTOP,  NULL, hInst, NULL );

    ShowWindow (hwnd, nCmdShow);
   
    /* creamos un hilo, en el que se crea el socket que aceptará las conexiones */
    hilo_socket =  CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SocketServidor,NULL, 0, &idHilo);
    if (hilo_socket == NULL) {
    MessageBox(NULL, "No puedo crear el hilo del socket de escucha", "CreateThread()", MB_ICONSTOP);
    return 2;
    }

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

    /* cerramos todas las conexiones abiertas */
    for (i = 0; i < MAX_CLIENT; i++)
if (sock_client[i])
   closesocket(sock_client[i]);

    WSACleanup();
   
    return msg.wParam;
}


/*---------------------------------------------------------------------------*/
LRESULT CALLBACK WndMainProc (HWND hWnd, UINT messg,
 WPARAM wParam, LPARAM lParam)
{
    RECT rc;
    switch (messg) {
        case WM_CREATE:
            /* creamos una ventana de edición */
            GetClientRect(hWnd, &rc);
        hWndEdit = CreateWindowEx(0, "edit", "", WS_CHILD|WS_VISIBLE|WS_BORDER|ES_MULTILINE|ES_WANTRETURN,
         0, 0, rc.right, rc.bottom, hWnd, NULL, hInstApp, NULL);
            if (hWndEdit != NULL) {
                /* cambiamos la función que gestiona la ventana de edición */
            old_fn_edit = (LRESULT CALLBACK(*)(HWND,UINT,WPARAM,LPARAM))
              SetWindowLong(hWndEdit, GWL_WNDPROC, (LONG)GestWndEdit);
SetFocus(hWndEdit);
   }
            break;
        case WM_SIZE:
            /* reajustamos el tamaño de la ventana de edición para que ocupe
               el área cliente de la ventana principal */
            if (wParam != SIZE_MINIMIZED)
            SetWindowPos(hWndEdit, hWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOMOVE);
            break;
        case WM_DESTROY:
            /* cerramos el socket y finalizamos el hilo */
   closesocket(sock_server);
            TerminateThread(hilo_socket, 0);
            PostQuitMessage (0);
            break;
    }
    return DefWindowProc (hWnd, messg, wParam, lParam);
}

/*---------------------------------------------------------------------------*/
/*  función que gestiona los mensajes de la ventana de edición */
LRESULT CALLBACK GestWndEdit(HWND hWnd, UINT messg,
WPARAM wParam, LPARAM lParam)
{
    int i, error;
    TCHAR caracter;
    if (messg == WM_CHAR) {
        /* enviamos el caracter introducido a todos los clientes activos */
        caracter = (TCHAR)wParam;
        for (i = 0; i < MAX_CLIENT; i++) {
           if (sock_client[i]) {
              error = send(sock_client[i], &caracter, sizeof(TCHAR), 0);
              /* si hay error, cerramos el socket (el cliente ha podido desconectar)*/
              if (error == SOCKET_ERROR) {
                 closesocket(sock_client[i]);
                 sock_client[i] = 0;
              }
           }
       }
    }
    /* pasamos el control a la función original que gestiona las ventanas de tipo "edit" */
    if (old_fn_edit)
    return old_fn_edit(hWnd, messg, wParam, lParam);

    return DefWindowProc(hWnd, messg, wParam, lParam);
}

/*---------------------------------------------------------------------------*/
DWORD SocketServidor(LPVOID lpvParam)
{
int i, error, num_socks;
    //SOCKET sock_server;
    struct sockaddr_in addr;
    fd_set fd;
   
    /* creamos un socket de tipo TCP */
    sock_server = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock_server == INVALID_SOCKET) {
        MessageBox(NULL,"No puedo crear socket servidor","socket()", MB_ICONSTOP);
        return 1;
    }
   
   
    ZeroMemory(&addr, sizeof(addr));
    addr.sin_family      = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;  /* recibimos de cualquier IP */
    addr.sin_port        = htons(PUERTO_SERVIDOR);  /* puerto que "escuchamos" */
   

    /* solicitamos al sistema que nos asocie el puerto */
    error = bind(sock_server, (struct sockaddr*)&addr, sizeof(addr));
    if (error == SOCKET_ERROR) {
        MessageBox(NULL, "No puedo asociar el socket de recepción","bind()", MB_ICONSTOP);
        closesocket(sock_server);
        return 2;
    }
   
    /* creamos una cola de espera de conexiones entrantes */
    if ( listen(sock_server, 5) ) {
        MessageBox(NULL, "Error creando cola de espera", "listen()", MB_ICONSTOP);
        closesocket(sock_server);
        return 3;
    }
   
    while (1) {
        FD_ZERO(&fd);
        FD_SET(sock_server, &fd);
       
        /* esperamos a que se conecten los clientes... */
        num_socks = select(0,&fd, NULL, NULL, NULL);
        if (num_socks == SOCKET_ERROR) {
MessageBox(NULL, "Error aceptando conexiones de clientes", "select()", MB_ICONSTOP);
            closesocket(sock_server);
            return 4;
        }
       
        /* ha finalizado el tiempo límite de recepción; aunque no le hemos dado un tiempo límite,
        he comprobado que en w98, a veces, select()  devuelve cero ¿¿???  */
        if (num_socks == 0)
        continue;
       
        if (FD_ISSET(sock_server, &fd)) {
       for (i = 0; i < MAX_CLIENT; i++) {
        if (sock_client[i] == 0) {
                 /* accept() devuelve un socket "conectado" al cliente */
                 sock_client[i] = accept(sock_server, NULL, NULL);
           if (sock_client[i] == INVALID_SOCKET) {
              MessageBox(NULL, "Error creando socket cliente", "accept()", MB_ICONSTOP);
              sock_client[i] = 0;
                 }
     break;
    }
  } /* for(...) */
         } /* if (FD_ISSET...) */
     } /* while(1) */
     
     return 0;
}
--- Fin del código ---


Este es el código del cliente

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

#define PUERTO_SERVIDOR 13527
#define MAX_BUFF 128

HWND hWndEdit;
HINSTANCE hInstApp;

char *ip_servidor = "127.0.0.1";
char *szClassName = "prueba_socket_cliente";

LRESULT CALLBACK WndMainProc (HWND, UINT, WPARAM, LPARAM);
void EscribeEdit(char*);
DWORD SocketCliente(LPVOID);

/*---------------------------------------------------------------------------*/
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst,
                    LPSTR lpszArgument,  int nCmdShow)
{
    HWND hwnd;
    MSG msg;
    WNDCLASSEX wincl = {0};
    HANDLE hilo_socket;
    DWORD idHilo;
    WSADATA wsadat;
    WORD version = MAKEWORD(1,1);

    /* inicializamos el entorno de windows sockets */
    if (WSAStartup( version, &wsadat)) {
    MessageBox(NULL, "Error inicializando windows sockets", "WSAStartup()", MB_ICONSTOP);
    return 1;
    }

    hInstApp = hInst;

    wincl.hInstance = hInst;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WndMainProc;
    wincl.style = CS_HREDRAW|CS_VREDRAW;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wincl))
        return 1;

    hwnd = CreateWindowEx (0, szClassName, "Cliente - sockets", WS_OVERLAPPEDWINDOW,
           CW_USEDEFAULT, CW_USEDEFAULT, 200, 200, HWND_DESKTOP,  NULL, hInst, NULL);
    ShowWindow (hwnd, nCmdShow);

/* creamos un hilo para gestionar el socket de recepción de datos */
    hilo_socket =  CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SocketCliente, NULL, 0, &idHilo);
    if (hilo_socket == NULL) {
    MessageBox(NULL, "No puedo crear el hilo del socket cliente", "CreateThread()", MB_ICONSTOP);
    return 2;
    }
    /* Ya no necesitamos este handle */
    CloseHandle(hilo_socket);

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

    WSACleanup();

    return msg.wParam;
}

/*---------------------------------------------------------------------------*/
LRESULT CALLBACK WndMainProc (HWND hWnd, UINT messg,
 WPARAM wParam, LPARAM lParam)
{
    RECT rc;
    switch (messg) {
        case WM_CREATE:
            GetClientRect(hWnd, &rc);
        hWndEdit = CreateWindowEx(0, "edit","",WS_CHILD|WS_VISIBLE|WS_BORDER|ES_MULTILINE|ES_WANTRETURN|ES_READONLY,
         0, 0, rc.right, rc.bottom, hWnd, NULL, hInstApp, NULL);
            break;
        case WM_SIZE:
            if (wParam != SIZE_MINIMIZED)
            SetWindowPos(hWndEdit, hWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOMOVE);
            break;
        case WM_DESTROY:
            PostQuitMessage (0);
            break;
    }
    return DefWindowProc (hWnd, messg, wParam, lParam);
}

/*---------------------------------------------------------------------------*/
void EscribeEdit(char *txt)
{
    SendMessage(hWndEdit, EM_SETSEL, -1, -1);
    SendMessage(hWndEdit, EM_REPLACESEL, 0, (LPARAM)txt);
}

/*---------------------------------------------------------------------------*/
DWORD SocketCliente(LPVOID lpvParam)
{
    SOCKET sock;
    struct sockaddr_in addr;
    fd_set fd;
    char buffer[MAX_BUFF];
    int error, bytes_leidos;

/* creamos un socket de tipo TCP */
    sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET) {
        EscribeEdit("No puedo crear socket cliente -- socket()\r\n");
        return 1;
    }

ZeroMemory(&addr, sizeof(addr));
    addr.sin_family        = AF_INET;
    addr.sin_addr.s_addr   = inet_addr(ip_servidor);
    addr.sin_port          = htons(PUERTO_SERVIDOR);

    /* intentamos conectar con el servidor */
    error = connect(sock, (struct sockaddr*)&addr, sizeof(addr));
    if (error == SOCKET_ERROR) {
        EscribeEdit("No puedo conectar con el servidor -- connect()\r\n");
      return 2;
    }

    /* escribimos en la ventana "edit" todo lo que recibimos */
    while (1) {
        ZeroMemory(buffer, MAX_BUFF);
        bytes_leidos = recv(sock, buffer, MAX_BUFF-1, 0);
        /* si bytes leidos == 0, el servidor ha cerrado la conexión */
        if (bytes_leidos < 1)
           break;
        EscribeEdit(buffer);
    }

    closesocket(sock);
    return 0;
}
--- Fin del código ---


Puedes probarlo con varios clientes abiertos simultáneamente. Abre primero el servidor, y luego los clientes. Todo lo que introduzcas en la ventana del servidor, lo verás escrito en los clientes.

Si tienes alguna duda, ya sabes...

(estoy viendo que se me ha jodío la indentación al pasarlo al bloc de notas.... :wink: )

Un saludo.

nota: los programas parecen un poco largos, pero la parte de los sockets no es tan grande. Casi todo se lo lleva la creación y gestión de las ventanas.

ElCorvaq:
A parte de los sockets quizá lo busques es esto

http://scv.bu.edu/Doc/Java/tutorial/native/index.html

Saludos

jirho:
...pues...estamos en buenas manos...como veo eso... :shock: ...por cierto...gracias...ElCorvaq...

likuid:
Muchas gracias por la ayuda, sigo liadisimo con lo de leer el puerto, vaya proyectito... y todo esto despues de 2 meses de curso en c, por no hablar del circuito que me he tenido que montar y enchufar a la linea telefonica, que es el que tengo que enganchar por otro lado al puerto paralelo... en fins :S

Que dios me pille confesado xd

[LiKuiD]

Navegación

[0] Índice de Mensajes

[*] Página Anterior

Ir a la versión completa