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.
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
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()
Antonio Linares wrote:Victor,
Si, posiblemente usar sockets funcione. No lo he probado
// 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
#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
https://github.com/FiveTechSoft/wsserver
//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( ) ) ) + ']......' )
Return to FiveWin para Harbour/xHarbour
Users browsing this forum: No registered users and 34 guests