HBSOCKET FUCIONAN BIEN LOS THREADS ?

Post Reply
User avatar
rterraz
Posts: 141
Joined: Wed Nov 08, 2006 11:44 pm
Location: Argentina

HBSOCKET FUCIONAN BIEN LOS THREADS ?

Post by rterraz »

Hola amigos
Estoy haciendo una aplicacion con FWH en la cual necesito implementar consultas a una DBF de un Servidor, en principio pense hacerlo via FTP pero estudiando los Socket creo que esa seria la mejor opcion.
Las consultas pueden ser muchas y puede ocurrir que varias se hagan en forma simultanea, probe usando los ejemplos de FWH pero tengo que hacer las mismas de a una y eso me origina muchos retrasos y bloqueos del servidor por lo que empece a estudiar la clase HBSOCKET de Daniel Garcia Gil que parece funcionar bien con las funciones de Harbour pero no llego a comprender bien como funciona el Multihilo, como controlarlos y como optimizar las funciones para evitar errorres en el Servidor.
Busque ejemplos, pero todos los que encontre me resultaron incompletos y muy basicos, he intentado comunicarme con Daniel via email a ver si el me puede aportar algun ejemplo mas completo de su uso pero aun no he tenido respuesta.
Agradeceria mucho si alguien me puede ilustrar con algun ejemplo de como usarla para lograr lo que necesito.
En resumen, consultas simultaneas de clientes que envian una cadena con datos al Servidor Socket que debe ser procesada por el mismo, que consulta a una o varias DBF y luego genera una respuesta que debe ser enviada al cliente que hizo la consulta.
No he encontrado documentacion que explicite el uso de las funciones incluidas en Harbour.
Como soy neofito en el uso de los sockets les estaria muy agradecido si pudieran orientarme en el tema
User avatar
Adolfo
Posts: 815
Joined: Tue Oct 11, 2005 11:57 am
Location: Chile
Contact:

Re: HBSOCKET FUCIONAN BIEN LOS THREADS ?

Post by Adolfo »

No reinventes la rueda.

Trata de probar LETODB y NETIO que te permiten acceder a las dbf de las siguiente forma

use //190.151.50.90/datos/clientes.dbf
;-) Ji,ji,ji... buena la cosa... "all you need is code"

http://www.xdata.cl - Desarrollo Inteligente
----------
Lenovo Legion Y520, 16GB Ram, 1 TB NVME M.2, 1 TB SSD, GTX 1050
User avatar
pablovidal
Posts: 398
Joined: Thu Oct 06, 2005 10:15 pm
Location: Republica Dominicana
Contact:

Re: HBSOCKET FUCIONAN BIEN LOS THREADS ?

Post by pablovidal »

Esto es un ejemplo..

Code: Select all

#include "inkey.ch"
#include "setcurs.ch"
#include "hbsocket.ch"
#include "hbclass.ch"
#include "std.ch"

#define CRLF                  chr(13)+chr(10)

Function Main()
Local nLinea :=  1

   
   SetMode( 40, 150 )
   SET COLOR TO "W+/B"
  
   CLS

 While lastkey() != 27
 nLinea :=  1
 clear
 
 hb_ThreadStart( @MainSocket(), nLinea, "ClientName", "HostName"    , nPuerto ) ;  Inkey(0.01) ; nLinea++ 
 hb_ThreadStart( @MainSocket(), nLinea, "ClientName", "HostName"    , nPuerto ) ;  Inkey(0.01) ; nLinea++
 hb_ThreadStart( @MainSocket(), nLinea, "ClientName", "HostName"    , nPuerto ) ;  Inkey(0.01) ; nLinea++ 
 Inkey(59)

 Enddo

Return Nil

Function MainSocket( nLinea, cBanca, cHostName, nPort )
Local oSocket
Local cInfo   := ""
Local nMill   := hb_MilliSeconds()

 @ nLinea, 01 Say cBanca + " : " + StrZero( nPort, 4 ) + " || "
 Hb_InetInit()

  oSocket := Hb_InetConnect( cHostName, nPort )
  hb_InetTimeout( oSocket, 30 )

  Hb_InetSend( oSocket, "#VER~" + CRLF )

  If ReadLine( oSocket, @cInfo )
   @ nLinea, 28 Say StrZero( hb_MilliSeconds() - nMill, 5 ) + " | " + cInfo
  End

  Hb_InetClose( oSocket )
  Hb_InetCleanup()

Return(  cInfo )


Static Function ReadLine( Socket, cInfo )
Local lRet := .t.
Local nBytes

   do while .t.
      if Hb_InetDataReady( Socket, 512 ) > 0
         BEGIN SEQUENCE
            cInfo := Hb_InetRecvLine( Socket, @nBytes )
         RECOVER
            lRet := .f.
         END

         exit
      endif
   enddo

   Return lRet


 
Saludos,

Pablo Alberto Vidal
/*
------------------------------------------------------
Harbour 3.2.0, Fivewin 17.02, BCC7
------------------------------------------------------
*/
User avatar
rterraz
Posts: 141
Joined: Wed Nov 08, 2006 11:44 pm
Location: Argentina

Re: HBSOCKET FUCIONAN BIEN LOS THREADS ?

Post by rterraz »

Gracias por sus respuestas...ya entendi como usar el Multithread, solo me faltaria saber como generar la consulta y enviar la respuesta al cliente usando HB_SOCKETSEND()
Estoy usando este codigo en el Socket Server

Code: Select all

#include 'fivewin.ch'
#include "hbsocket.ch"

#define ADDRESS                     "0.0.0.0"
#define PORT                        8000
#define EOT                         ( Chr( 4 ) )
#define LISTEN_TIMEOUT              3000            // 3s
#define RECV_TIMEOUT                10000           // 10s

STATIC oWnd,oBar,hListen,hSocket

*REQUEST HB_MT

//..............
Function main()

    DEFINE WINDOW oWnd TITLE 'Server Socket'

    DEFINE BUTTONBAR oBar OF oWnd _3D 2007

    DEFINE BUTTON FILE '.\connect.bmp' OF oBar ACTION Server() TOOLTIP "Listen"
    DEFINE BUTTON FILE '.\door.bmp'  OF oBar ACTION oWnd:end()

*    DEFINE BUTTON OF oBar ACTION oClient:SendData( "Hello from server!" ) TOOLTIP "Talk to client"

    ACTIVATE WINDOW oWnd


RETU .T.


//....................
Function Server()

    if !hb_mtvm()
        ? "soporte multithread es requerido..."+CRLF+;
          "Compile: Buildh Ipserver /mt"
        return .T.
    else
        ? 'Mutithread activo'
    endif

    ? "create listening socket..."
    if empty( hListen := hb_socketOpen() )
        ? "socket create error " + hb_ntos( hb_socketGetError() )
    endif
    if !hb_socketBind( hListen, { HB_SOCKET_AF_INET, ADDRESS, PORT } )
        ? "bind error " + hb_ntos( hb_socketGetError() )
    endif
    if !hb_socketListen( hListen )
        ? "listen error " + hb_ntos( hb_socketGetError() )
    else
        ? 'A la escucha...'
    endif

    oWnd:SetText('Socket a la escucha...')

    do while .t.

        if empty( hSocket := hb_socketAccept( hListen, , LISTEN_TIMEOUT ) )
            if hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT
   *             ? "loop..."
            else
                ? "accept error " + hb_ntos( hb_socketGetError() )
            endif
        else
  *          ? "accept socket request"
            hb_threadDetach( hb_threadStart( @process(), hSocket ) )
        endif
        if getkeystate(VK_ESC)
            ? 'Socket detenido...'
            exit
        endif
    enddo

    oWnd:SetText('Escucha Detenida...')        // ? "close listening socket..."
    hb_socketShutdown( hListen )
    hb_socketClose( hListen )

return NIL

//..........................
Function process( hSocket )

    local cRequest
    local nLen
    local cBuf
      
 do while .t.
        cRequest := ""
        nLen := 1
        do while at( EOT, cRequest ) == 0 .and. nLen > 0
            cBuf := space( 4096 )
            if ( nLen := hb_socketRecv( hSocket, @cBuf, , , RECV_TIMEOUT ) ) > 0
                cRequest += left( cBuf, nLen )
            else
                if nLen == -1 .AND. hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT
                    nLen := 0
                endif
            endif
        enddo


        if nLen == -1
            ? "hb_socketRecv error " + hb_ntos( hb_socketGetError() )
        elseif nLen == 0
            ? "connection closed"
            exit
        else
   *         if "exit" $ cRequest
            if EOT $ cResquest
                ? "exit"
                exit
            endif
        endif
    enddo


     ? "close socket..."
    hb_socketShutdown( hSocket )
    hb_socketClose( hSocket )

return NIL

 

La funcion Process me devuelve siempre el largo de la cadena que envio desde el acliente...
En lugar de ello necesito hacer una consulta a una DBF y luego enviar mi respuesta al Cliente
Espero que puedan ayudarme porque no logro entender como hacerlo
Post Reply