Creando Servicios con Harbour y xHarbour
Re: Creando Servicios con Harbour y xHarbour
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.
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) ]
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) ]
- wilsongamboa
- Posts: 600
- Joined: Wed Oct 19, 2005 6:41 pm
- Location: Quito - Ecuador
Re: Creando Servicios con Harbour y xHarbour
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
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
Wilson.josenet@gmail.com
- Antonio Linares
- Site Admin
- Posts: 42259
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: Creando Servicios con Harbour y xHarbour
Funciona correctamente con Harbour y xHarbourleandro 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.
- Antonio Linares
- Site Admin
- Posts: 42259
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: Creando Servicios con Harbour y xHarbour
la gran limitación es que no se puede usar NADA de GUI. Ni siquiera ni un MsgInfo() ó MsgBeep()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
- wilsongamboa
- Posts: 600
- Joined: Wed Oct 19, 2005 6:41 pm
- Location: Quito - Ecuador
Re: Creando Servicios con Harbour y xHarbour
gracias antonio por contestar
pero sirve para programas multihilos ? que no tengan salida a pantalla claro
saludos
pero sirve para programas multihilos ? que no tengan salida a pantalla claro
saludos
Wilson 'W' Gamboa A
Wilson.josenet@gmail.com
Wilson.josenet@gmail.com
- Antonio Linares
- Site Admin
- Posts: 42259
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: Creando Servicios con Harbour y xHarbour
Wilson,
habria que probarlo pero supongo que si, que debe funcionar multihilo correctamente
habria que probarlo pero supongo que si, que debe funcionar multihilo correctamente
- VictorCasajuana
- Posts: 268
- Joined: Wed Mar 28, 2018 4:38 pm
- Location: Vinaròs
- Contact:
Re: Creando Servicios con Harbour y xHarbour
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?Antonio Linares wrote:la gran limitación es que no se puede usar NADA de GUI. Ni siquiera ni un MsgInfo() ó MsgBeep()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
Gracias y salud!
--------
¿ Y porque no ?
¿ And why not ?
¿ Y porque no ?
¿ And why not ?
- Antonio Linares
- Site Admin
- Posts: 42259
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: Creando Servicios con Harbour y xHarbour
Victor,
Si, posiblemente usar sockets funcione. No lo he probado
Si, posiblemente usar sockets funcione. No lo he probado
- VictorCasajuana
- Posts: 268
- Joined: Wed Mar 28, 2018 4:38 pm
- Location: Vinaròs
- Contact:
Re: Creando Servicios con Harbour y xHarbour
Hola Antonio.Antonio Linares wrote:Victor,
Si, posiblemente usar sockets funcione. No lo he probado
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
// 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
En cambio si lo compilo con buildhmt.bat, no llega a ejecutar la función Listen(), se queda ahí:
puede ser algo de la función del servicio?
Gracias!!
--------
¿ Y porque no ?
¿ And why not ?
¿ Y porque no ?
¿ And why not ?
- VictorCasajuana
- Posts: 268
- Joined: Wed Mar 28, 2018 4:38 pm
- Location: Vinaròs
- Contact:
Re: Creando Servicios con Harbour y xHarbour
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!
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 ?
¿ Y porque no ?
¿ And why not ?
- Antonio Linares
- Site Admin
- Posts: 42259
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: Creando Servicios con Harbour y xHarbour
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
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
Re: Creando Servicios con Harbour y xHarbour
Un ejemplo sacado de hbwin/tests
Code: Select all | Expand
#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
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
- VictorCasajuana
- Posts: 268
- Joined: Wed Mar 28, 2018 4:38 pm
- Location: Vinaròs
- Contact:
Re: Creando Servicios con Harbour y xHarbour
partiendo del repositorio : 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.
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.
Gracias Antonio por tu código y consejos y también al resto por ayudarme.
Salud!
Code: Select all | Expand
https://github.com/FiveTechSoft/wsserver
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
//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( ) ) ) + ']......' )
Gracias Antonio por tu código y consejos y también al resto por ayudarme.
Salud!
--------
¿ Y porque no ?
¿ And why not ?
¿ Y porque no ?
¿ And why not ?
- wilsongamboa
- Posts: 600
- Joined: Wed Oct 19, 2005 6:41 pm
- Location: Quito - Ecuador
Re: Creando Servicios con Harbour y xHarbour
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
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
Wilson.josenet@gmail.com