Creando Servicios con Harbour y xHarbour

Re: Creando Servicios con Harbour y xHarbour

Postby leandro » Wed Sep 18, 2024 3:54 pm

Antonio gracias como siempre por todo

Esto ya lo podemos usar en xharbour? o solo es para harbour? no entendí bien el mensaje?, la traducción en google no es muy clara.
Saludos
LEANDRO AREVALO
Bogotá (Colombia)
https://hymlyma.com
https://hymplus.com/
leandroalfonso111@gmail.com
leandroalfonso111@hotmail.com

[ Embarcadero C++ 7.60 for Win32 ] [ FiveWin 23.07 ] [ xHarbour 1.3.0 Intl. (SimpLex) (Build 20230914) ]
User avatar
leandro
 
Posts: 1669
Joined: Wed Oct 26, 2005 2:49 pm
Location: Colombia

Re: Creando Servicios con Harbour y xHarbour

Postby wilsongamboa » Wed Sep 18, 2024 4:08 pm

buenos dias con todos magino que la funcion
TrabajoServicio() va a reempalzar a la entrada o main de nuestra aplicacion solo una pregunta esto funciona para los programas multihilo ?? como hbnetio o como hbhttpd ?
gracias por todo Masters !!
saludos
Wilson 'W' Gamboa A
Wilson.josenet@gmail.com
User avatar
wilsongamboa
 
Posts: 593
Joined: Wed Oct 19, 2005 6:41 pm
Location: Quito - Ecuador

Re: Creando Servicios con Harbour y xHarbour

Postby Antonio Linares » Wed Sep 18, 2024 4:13 pm

leandro wrote:Antonio gracias como siempre por todo

Esto ya lo podemos usar en xharbour? o solo es para harbour? no entendí bien el mensaje?, la traducción en google no es muy clara.


Funciona correctamente con Harbour y xHarbour
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42065
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Creando Servicios con Harbour y xHarbour

Postby Antonio Linares » Wed Sep 18, 2024 4:15 pm

wilsongamboa wrote:buenos dias con todos magino que la funcion
TrabajoServicio() va a reempalzar a la entrada o main de nuestra aplicacion solo una pregunta esto funciona para los programas multihilo ?? como hbnetio o como hbhttpd ?
gracias por todo Masters !!
saludos

la gran limitación es que no se puede usar NADA de GUI. Ni siquiera ni un MsgInfo() ó MsgBeep()
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42065
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Creando Servicios con Harbour y xHarbour

Postby wilsongamboa » Wed Sep 18, 2024 4:34 pm

gracias antonio por contestar
pero sirve para programas multihilos ? que no tengan salida a pantalla claro
saludos
Wilson 'W' Gamboa A
Wilson.josenet@gmail.com
User avatar
wilsongamboa
 
Posts: 593
Joined: Wed Oct 19, 2005 6:41 pm
Location: Quito - Ecuador

Re: Creando Servicios con Harbour y xHarbour

Postby Antonio Linares » Wed Sep 18, 2024 4:43 pm

Wilson,

habria que probarlo pero supongo que si, que debe funcionar multihilo correctamente
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42065
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Creando Servicios con Harbour y xHarbour

Postby VictorCasajuana » Sat Oct 12, 2024 8:37 am

Antonio Linares wrote:
wilsongamboa wrote:buenos dias con todos magino que la funcion
TrabajoServicio() va a reempalzar a la entrada o main de nuestra aplicacion solo una pregunta esto funciona para los programas multihilo ?? como hbnetio o como hbhttpd ?
gracias por todo Masters !!
saludos

la gran limitación es que no se puede usar NADA de GUI. Ni siquiera ni un MsgInfo() ó MsgBeep()


Hola Antonio. Partiendo de tener un servicio realizado con FWH, con las ventajas que supone pero la limitación de no poder interactuar con él de primeras. Cuál sería la forma más correcta para comunicarse con el servicio mediante otro programa de FWH? me refiero a montar otro programa que sí ejecuta el usuario cuando abre sesión y desde dicho programa, poder interactuar con el servicio para lanzar acciones, ver su estado, etc... Se me ocurre utilizar sockets?

Gracias y salud!
--------
¿ Y porque no ?
¿ And why not ?
User avatar
VictorCasajuana
 
Posts: 260
Joined: Wed Mar 28, 2018 4:38 pm
Location: Vinaròs

Re: Creando Servicios con Harbour y xHarbour

Postby Antonio Linares » Sat Oct 12, 2024 10:17 am

Victor,

Si, posiblemente usar sockets funcione. No lo he probado
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42065
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Creando Servicios con Harbour y xHarbour

Postby VictorCasajuana » Sat Oct 12, 2024 4:28 pm

Antonio Linares wrote:Victor,

Si, posiblemente usar sockets funcione. No lo he probado

Hola Antonio.
Montando un ejemplo funcional con sockets, me ha funcionado. La conexión la realizo con postman para hacer las pruebas iniciales, luego si soluciono lo que te comento, haré un cliente para las pruebas básicas de interacción con el servicio. El problema es cuando activo el multithread para que después de aceptar una conexión, se quede escuchando de nuevo. Esto lo hago con algunas utilidades que tengo montadas con sockets y mt y me funciona perfectamente, pero en este caso no me funciona, no sé si es porque hay que adaptar la función que has realizado para el servicio en C a multithread, ahí me pierdo.

Con el siguiente código:
Code: Select all  Expand view
// Once you build the EXE open a CMD window as Administrator, then:
// sc create servicio binPath=c:\fwh\samples\servicio.exe
// sc start servicio
// when you want to stop it: sc stop servicio
// when you want to remove it: sc delete servicio
// DON'T USE ANY GUI FROM IT !!!

#include "FiveWin.ch"
#include "hbsocket.ch"


function Main()
   
    Local nPuerto := 8500

    public hListen := Nil
    public log := "c:\servicio.log"

    fErase( log )
    hb_MemoWrit( log, hb_MemoRead( log) + hb_Eol() + 'iniciando socketserver' )
    hListen := hb_socketOpen( HB_SOCKET_AF_INET, HB_SOCKET_PT_STREAM, HB_SOCKET_IPPROTO_TCP )
    hb_socketBind( hListen, { HB_SOCKET_AF_INET, '0.0.0.0', nPUerto } )
    hb_socketListen( hListen )
    hb_MemoWrit( log, hb_MemoRead( log) + hb_Eol() + 'socketserver iniciado en puerto ' + Str(nPUerto) )

    Servicio()

return nil

Function Listen()

    Local hSocket := Nil

    hb_MemoWrit( log, hb_MemoRead( log) + hb_Eol() + Time() +'Escuchando puerto' )

    hSocket := hb_socketAccept( hListen,, 1000  )

    if Empty( hSocket )

        if hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT

                // No se hace nada, simplemente a superado el tiempo de espera para recibir una petición de conexión

        Else

            hb_MemoWrit( log, hb_MemoRead( log) + hb_Eol() + 'accept error ' + hb_ntos( hb_socketGetError() ) )

        endif

    Else

        hb_MemoWrit( log, hb_MemoRead( log) + hb_Eol() + 'conexión aceptada' )
        hb_threadDetach( hb_threadStart( @ServeClient(), hSocket, Self ) )

    endif

Return ( Nil )

Function ServeClient()

    hb_MemoWrit( log, hb_MemoRead( log) + hb_Eol() + 'ejecutando thread del cliente' )

Return ( Nil )

#pragma BEGINDUMP

#include <windows.h>
#include <tchar.h>
#include <hbvm.h>

SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;

void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
int InitService( void );

HB_FUNC( SERVICIO )
{
    SERVICE_TABLE_ENTRY ServiceTable[2];
    ServiceTable[0].lpServiceName = _T("Servicio");
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;

    StartServiceCtrlDispatcher(ServiceTable);
}

#pragma warn -8057

void ServiceMain(int argc, char** argv )
{
    ServiceStatus.dwServiceType        = SERVICE_WIN32;
    ServiceStatus.dwCurrentState       = SERVICE_START_PENDING;
    ServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    ServiceStatus.dwWin32ExitCode      = 0;
    ServiceStatus.dwServiceSpecificExitCode = 0;
    ServiceStatus.dwCheckPoint         = 0;
    ServiceStatus.dwWaitHint           = 0;

    hStatus = RegisterServiceCtrlHandler(_T("Servicio"), (LPHANDLER_FUNCTION)ControlHandler);

    if (InitService() == 0)
    {
        ServiceStatus.dwCurrentState = SERVICE_RUNNING;
        SetServiceStatus(hStatus, &ServiceStatus);

        // Aquí va el bucle principal del servicio
        while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
        {
            // Realiza las tareas del servicio
            hb_vmPushSymbol( hb_dynsymSymbol( hb_dynsymFindName( "LISTEN" ) ) );
            hb_vmPushNil();
            hb_vmDo( 0 );

            // Sleep(1000); ya lo hago en el hb_socketaccept
        }
    }

    ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    SetServiceStatus(hStatus, &ServiceStatus);
}

void ControlHandler(DWORD request)
{
    switch(request)
    {
        case SERVICE_CONTROL_STOP:
            ServiceStatus.dwWin32ExitCode = 0;
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            SetServiceStatus(hStatus, &ServiceStatus);
            MessageBox( 0, "service stopped", "ok", 0 );
            return;
        case SERVICE_CONTROL_SHUTDOWN:
            ServiceStatus.dwWin32ExitCode = 0;
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            SetServiceStatus(hStatus, &ServiceStatus);
            return;
        default:
            break;
    }
    SetServiceStatus(hStatus, &ServiceStatus);
}

int InitService()
{
    // Inicialización del servicio
    return 0;
}

#pragma ENDDUMP


El resultado siguiente es compilado con buildh.bat, funciona correctamente pero al recibir la conexión se para la escucha:
Image

En cambio si lo compilo con buildhmt.bat, no llega a ejecutar la función Listen(), se queda ahí:
Image

puede ser algo de la función del servicio?

Gracias!!
--------
¿ Y porque no ?
¿ And why not ?
User avatar
VictorCasajuana
 
Posts: 260
Joined: Wed Mar 28, 2018 4:38 pm
Location: Vinaròs

Re: Creando Servicios con Harbour y xHarbour

Postby VictorCasajuana » Sat Oct 12, 2024 4:32 pm

Algunas cosas que me he encontrado jugando con los servicios por si alguien llega por aquí y le pueden ser útiles:
sc config servicio5 start= auto configura el servicio para que se ejecute automáticamente al iniciar windows.

A veces te vuelve loco el tema del servicio, puede que lo tengas parado pero cuando compilas te indica el compilador que se está ejecutando el programa y a veces te deja compilar con el servicio en marcha y el servicio te ejecuta el último exe que has compilado automáticamente. Supongo que es porque los servicios de windows van con algún delay interno

Cuando se borra un servicio, en ocasioners no lo hace inmediato, a veces hay que reiniciar

El binPath ha de ser con la ruta completa, de lo contrario lo crea pero luego cuando lo inicias no encuentra el .exe

Salud!
--------
¿ Y porque no ?
¿ And why not ?
User avatar
VictorCasajuana
 
Posts: 260
Joined: Wed Mar 28, 2018 4:38 pm
Location: Vinaròs

Re: Creando Servicios con Harbour y xHarbour

Postby Antonio Linares » Sat Oct 12, 2024 7:35 pm

Victor,

Lo suyo sería construirlo solo con Harbour y no usar FWH porque si hay un error el GUI intentará mostrarse y ahi quedará bloqueado
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42065
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Creando Servicios con Harbour y xHarbour

Postby cnavarro » Sun Oct 13, 2024 4:39 pm

Un ejemplo sacado de hbwin/tests

Code: Select all  Expand view

#define _SERVICE_NAME "Harbour_Test_Service"

PROCEDURE Main( cMode )

   LOCAL nError
   LOCAL cMsg

   hb_default( @cMode, "S" ) /* NOTE: Must be the default action */

   SWITCH Upper( cMode )
   CASE "I"

      IF win_serviceInstall( _SERVICE_NAME, "Harbour Windows Test Service" )
         ? "Service has been successfully installed"
      ELSE
         nError := wapi_GetLastError()
         cMsg := Space( 128 )
         wapi_FormatMessage( ,,,, @cMsg )
         ? "Error installing service: " + hb_ntos( nError ) + " " + cMsg
      ENDIF
      EXIT

   CASE "U"

      IF win_serviceDelete( _SERVICE_NAME )
         ? "Service has been deleted"
      ELSE
         nError := wapi_GetLastError()
         cMsg := Space( 128 )
         wapi_FormatMessage( ,,,, @cMsg )
         ? "Error deleting service: " + hb_ntos( nError ) + " " + cMsg
      ENDIF
      EXIT

   CASE "S"

      /* NOTE: Used when starting up as service.
               Do not invoke the executable manually with this option */


      IF win_serviceStart( _SERVICE_NAME, @SrvMain() )
         ? "Service has started OK"
      ELSE
         nError := wapi_GetLastError()
         cMsg := Space( 128 )
         wapi_FormatMessage( ,,,, @cMsg )
         ? "Service has had some problems: " + hb_ntos( nError ) + " " + cMsg
      ENDIF
      EXIT

   ENDSWITCH

   RETURN

#include "fileio.ch"

PROCEDURE SrvMain( cParam1, cParam2 )

   LOCAL n := 0
   LOCAL fhnd := hb_FCreate( hb_FNameExtSet( hb_ProgName(), ".out" ), FC_NORMAL, FO_DENYNONE + FO_WRITE )
   LOCAL cParam

   hb_default( @cParam1, "" )
   hb_default( @cParam2, "" )

   FWrite( fhnd, "Startup" + hb_eol() )
   FWrite( fhnd, "|" + hb_CmdLine() + "|" + hb_eol() )
   FWrite( fhnd, "|" + cParam1 + "|" + cParam2 + "|" + hb_eol() )

   FOR EACH cParam IN hb_AParams()
      FWrite( fhnd, "Parameter " + hb_ntos( cParam:__enumIndex() ) + " >" + cParam + "<" + hb_eol() )
   NEXT

   DO WHILE win_serviceGetStatus() == WIN_SERVICE_RUNNING
      FWrite( fhnd, "Work in progress " + hb_ntos( ++n ) + hb_eol() )
      hb_idleSleep( 0.5 )
   ENDDO

   FWrite( fhnd, "Exiting..." + hb_eol() )
   FClose( fhnd )

   win_serviceSetExitCode( 0 )
   win_serviceStop()

   RETURN


 
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6541
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Creando Servicios con Harbour y xHarbour

Postby VictorCasajuana » Mon Oct 14, 2024 5:56 pm

partiendo del repositorio :
Code: Select all  Expand view
https://github.com/FiveTechSoft/wsserver
y aplicado como servicio, pongo un pequeño ejemplo funcional:
es un servicio que incluye un servidor de sockets con multithread para procesar multiples conexiones simultáneas que permiten interactuar con el servicio.

Code: Select all  Expand view
//TODO: Definir el path del hb_out.log

#include 'hbwin.ch'
#include "hbsocket.ch"

#DEFINE SERVICE_NAME 'aaa'
#DEFINE HOST '0.0.0.0'
#DEFINE PUERTO 8500
#DEFINE LISTEN_TIMEOUT 1000
#DEFINE LOG 'c:\servicio_hb.log'
#define FILEHEADER "data:application/octet-stream;base64,"
#define JSONHEADER "data:application/json;base64,"
#define HTMLHEADER "data:text/html;base64,"

Function Main()

    fErase( LOG )
    win_serviceStart( SERVICE_NAME, @Servicio() )

Return ( Nil )

Function Servicio()

    Local hListen := Nil
    lOCAL hSocket := Nil

    hListen := hb_socketOpen( HB_SOCKET_AF_INET, HB_SOCKET_PT_STREAM, HB_SOCKET_IPPROTO_TCP )
    hb_socketBind( hListen, { HB_SOCKET_AF_INET, HOST, PUERTO } )
    hb_socketListen( hListen )

    if .Not. hb_mtvm()

        LogServer( 'Multithread no disponible. El servicio no se iniciará'  )
        win_serviceSetExitCode( 1 )
        win_serviceStop()
        Return ( Nil )

    Else

        LogServer( 'Multithread disponible'  )

    Endif


    LogServer( 'socketserver iniciado en puerto ' + Str(PUERTO) )

    While win_serviceGetStatus() == WIN_SERVICE_RUNNING

        LogServer( Time() +' Escuchando puerto' + Str( PUERTO ) )

        hSocket := hb_socketAccept( hListen,, LISTEN_TIMEOUT  )
   
        if Empty( hSocket )
   
            if hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT
   
                    // No se hace nada, simplemente a superado el tiempo de espera para recibir una petición de conexión
   
            Else
   
                LogServer( 'accept error ' + hb_ntos( hb_socketGetError() ) )
   
            endif
   
        Else
   
            LogServer( 'conexión aceptada' )
            hb_threadDetach( hb_threadStart( @ServeClient(), hSocket ) )
   
        endif

    Enddo

    win_serviceSetExitCode( 0 )
    win_serviceStop()

Return ( Nil )

Function ServeClient( hSocket )

    Local cBuffer := Space( 4096 )
    Local lConnectionClosed := .F.
    Local nLen := 0
    Local cRequest := ''
    Local nOpcode := 0

    hb_socketRecv( hSocket, @cBuffer,,, 1024 )
    HandShaking( RTrim( cBuffer ), hSocket )

    while .Not. lConnectionClosed

        LogServer( ThreadId() + ' Esperando petición de cliente' )

        cRequest := ''
        nLen := 1

        while nLen > 0

            cBuffer := Space( 4096 )

            if ( nLen := hb_socketRecv( hSocket, @cBuffer,,, LISTEN_TIMEOUT ) ) > 0  

                cRequest += Left( cBuffer, nLen )

            else

                if nLen == -1 .and. hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT

                    nLen = 0

                endif

            endif

        Enddo

        If !Empty( cRequest )

            cRequest:= UnMask( cRequest, @nOpcode )

            LogServer( ThreadId() + ' Respuesta:' + cRequest )

            switch cRequest

                case 'ACCION1'

                    LogServer( ThreadId() + ' Ejecutando la acción 1' )
                    hb_idleSleep( 1 )
                    LogServer( ThreadId() + ' Fin acción 1' )
                   
                exit

                case 'ACCION2'

                    LogServer( ThreadId() + ' Ejecutando la acción 2' )
                    hb_idleSleep( 1 )
                    LogServer( ThreadId() + ' Fin acción 2' )
                   
                exit

                case 'EXIT'

                    lConnectionClosed := .T.
                    LogServer( ThreadId() + ' Se solicita desconexión' )

                exit

                otherwise

                    LogServer( ThreadId() + ' Petición desconocida ' + cRequest )

                exit

            endswitch

        Else

            //LogServer( 'Se ha recibido una petición vacia ' + cRequest )

        Endif

    Enddo

    LogServer( 'Desconectando Socket' )
    hb_socketShutdown( hSocket )
    LogServer( 'Cerrando Socket' )
    hb_socketClose( hSocket )

Return ( Nil )

Static Function HandShaking( cHeaders, hSocket )

    local aHeaders as Array := hb_ATokens( cHeaders, hb_Eol() )
    local hHeaders as Hash := {=>}
    Local cLine  as Character := ''
    local cAnswer as Character := ''
     
    for each cLine in aHeaders

        hHeaders[ SubStr( cLine, 1, At( ":", cLine ) - 1 ) ] = SubStr( cLine, At( ":", cLine ) + 2 )

    next
     
    cAnswer = "HTTP/1.1 101 Web Socket Protocol Handshake" + Hb_Eol() + ;
              "Upgrade: websocket" + Hb_Eol() + ;
              "Connection: Upgrade" + Hb_Eol() + ;
              "WebSocket-Origin: " + HOST + Hb_Eol() + ;
              "WebSocket-Location: ws://" + HOST + ":" + hb_ntos( PUERTO ) + Hb_Eol() + ;
              "Sec-WebSocket-Accept: " + ;
              hb_Base64Encode( hb_SHA1( hHeaders[ "Sec-WebSocket-Key" ] + ;
                               "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", .T. ) ) + Hb_Eol() + Hb_Eol()
   
    LogServer( 'Enviando HandShaking' )
    hb_socketSend( hSocket, cAnswer )
     
Return ( Nil )

Static function Unmask( cBytes, nOpcode )
   
    local lComplete := hb_bitTest( hb_bPeek( cBytes, 1 ), 7 )
    local nFrameLen := hb_bitAnd( hb_bPeek( cBytes, 2 ), 127 )
    local nLength, cMask, cData, cChar, cHeader := ""
 
    nOpcode := hb_bitAnd( hb_bPeek( cBytes, 1 ), 15 )
 
    do case
       case nFrameLen <= 125
          nLength = nFrameLen
          cMask = SubStr( cBytes, 3, 4 )
          cData = SubStr( cBytes, 7 )
 
       case nFrameLen = 126
          nLength = ( hb_bPeek( cBytes, 3 ) * 256 ) + hb_bPeek( cBytes, 4 )
          cMask   = SubStr( cBytes, 5, 4 )
          cData   = SubStr( cBytes, 9 )
 
       case nFrameLen = 127  
          nLength = NetworkBin2ULL( SubStr( cBytes, 3, 8 ) )  
          cMask   = SubStr( cBytes, 11, 4 )
          cData   = SubStr( cBytes, 15 )
    endcase
 
    cBytes = ""

    for each cChar in cData
       cBytes += Chr( hb_bitXor( Asc( cChar ),;
                      hb_bPeek( cMask, ( ( cChar:__enumIndex() - 1 ) % 4 ) + 1 ) ) )
    next  
 
    do case
       case Left( cBytes, Len( FILEHEADER ) ) == FILEHEADER
          cBytes = hb_base64Decode( SubStr( cBytes, Len( FILEHEADER ) + 1 ) )
          cHeader = FILEHEADER
 
       case Left( cBytes, Len( JSONHEADER ) ) == JSONHEADER
          cBytes = hb_base64Decode( SubStr( cBytes, Len( JSONHEADER ) + 1 ) )
          cHeader = JSONHEADER
 
       case Left( cBytes, Len( HTMLHEADER ) ) == HTMLHEADER
          cBytes = hb_base64Decode( SubStr( cBytes, Len( HTMLHEADER ) + 1 ) )
          cheader = HTMLHEADER
    endcase
   
 return cBytes

  Static function NetworkBin2ULL( cBytes )

    local cByte, n := 0
   
    for each cByte in cBytes

       n += hb_BitShift( Asc( cByte ), 64 - cByte:__enumIndex() * 8 )

    next
   
 return n

 function NetworkULL2Bin( n )

    local nBytesLeft := 64
    local cBytes := ""
 
    while nBytesLeft > 0

       nBytesLeft -= 8
       cBytes += Chr( hb_BitAnd( hb_BitShift( n, -nBytesLeft ), 0xFF ) )

    end
 
 return cBytes
 
Static Function LogServer( cMessage )

    hb_MemoWrit( LOG, hb_MemoRead( LOG ) + hb_Eol() + cMessage )

Return ( Nil )

Static Function ThreadId()
Return ( '[' + hb_ntos( hb_threadId( hb_threadSelf( ) ) ) + ']......' )


Aquí una pequeña demo donde se ve el estado inicial del servicio, como se inicia, dos peticiones simultáneas por postman ( se pueden hacer mediante un cliente ce HB, javascript, o lo que uno quiera ) lo que se ejecuta dentro de cada petición lleva entre corchetes el thread correspondiente, y todo reflejado en un log, sin GUI para que no haya problemas de interrupciones del servicio por errores. Por supuesto, al ser un servicio ha de llevar un control de errores de cada acción que se hace, pero esto es solo una pequeña demo funcional que he montado por si a alguien le sirve.

Image

Gracias Antonio por tu código y consejos y también al resto por ayudarme.

Salud!
--------
¿ Y porque no ?
¿ And why not ?
User avatar
VictorCasajuana
 
Posts: 260
Joined: Wed Mar 28, 2018 4:38 pm
Location: Vinaròs

Re: Creando Servicios con Harbour y xHarbour

Postby wilsongamboa » Mon Oct 14, 2024 7:59 pm

Felicitaciones Victor excelente tu trabajo
podrias poner un cliente con harbour para los que no tenemos mucha idea
que envie datos a ese server y recoja la respuesta

gracias
Wilson
Wilson 'W' Gamboa A
Wilson.josenet@gmail.com
User avatar
wilsongamboa
 
Posts: 593
Joined: Wed Oct 19, 2005 6:41 pm
Location: Quito - Ecuador

Previous

Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 62 guests