Vai ai mais umas de minhas experiências com o uso de Fivewin e tratamento de conecções via socket com enfase em manutenção de dados.
Os testes foram de envio de mensagens, envio de comandos e envio de vetor de strings para salvar em tabelas.
A unica interação do usuário será a de colocar o IP do servidor no arquivo .INI do cliente.
[SERVIDOR]
NAME=5VSERVER
IP=192.168.0.1
Depois é só testar os comandos da parte cliente e ver as respostas no servidor.
Os testes foram feitos usando uma rede wireless adhoc. Em uma ligação via internet com roteadores deverá existir a liberação de IP visiveis na internet.
SOC2CLI.PRG
// Socket server connection sample
#include "FiveWin.ch"
#define ST_COMMAND 1
#define ST_SENDFILE 2
#define FILE_BLOCK 8000
static oWnd, oSocket
static hLib, hDib
static xdll
//------------------------------------------------------------------------//
function Main(cHostIP)
local oBar
// **********************************************************************
cPath := cFilePath( GetModuleFileName( GetInstance() ) )
// Pega nome da maquina
cNetName := NETNAME()
// Pega IP da maquina
WsaStartUp() ; cClientIP := getHostByName( cNetName ) ; WsaCleanUp()
// Salva dados
cClientIP := VerifyINI( cNetName , "IP" , cClientIP , cPath+"soc2cli.ini" )
cClientName := VerifyINI( cNetName , "NAME", cNetName , cPath+"soc2cli.ini" )
//
cSite := VerifyINI( "SERVICE", "SITE" , "http://www.5volution.com.br", cPath+"soc2cli.ini" )
//cTXTIP := VerifyINI( "SERVICE", "TXTIP", cSite + "/netsrv.txt" , cPath+"soc2cli.ini" )
//
cHostIP := getIPExtern( cSite + "/netsrv.txt" )
//
cHostIP := VerifyINI( "SERVIDOR", "IP" , cHostIP , cPath+"soc2cli.ini" )
cHostName := VerifyINI( "SERVIDOR", "NAME", "5VSERVER", cPath+"soc2cli.ini" )
//
// **********************************************************************
DEFINE WINDOW oWnd TITLE "Cliente: "+alltrim(cNetName)+" IP: "+cClientName+"("+cHostIP+")"
DEFINE BUTTONBAR oBar OF oWnd _3D
DEFINE BUTTON OF oBar ACTION Client( cHostIP ) TOOLTIP "Conectar"
//DEFINE BUTTON OF oBar ACTION SendCMD( "QUIT" ) TOOLTIP "Derrubar servidor"
DEFINE BUTTON OF oBar ;
ACTION oSocket:SendData( "MSG Mensagem de teste!" ) ;
TOOLTIP "Send data"
DEFINE BUTTON OF oBar ;
ACTION SendData() TOOLTIP "Send data"
DEFINE BUTTON OF oBar ;
ACTION SaveData() TOOLTIP "Save data"
DEFINE BUTTON OF oBar ;
ACTION SendSearch() TOOLTIP "Send search"
ACTIVATE WINDOW oWnd ON INIT Client( cHostIP )
return nil
//------------------------------------------------------------------------//
function Client( cIP )
oSocket = TSocket():New( 2000 )
//oSocket:bRead = { | oSocket | OnRead( oSocket ) }
oSocket:bConnect = { || oWnd:SetText( "Conectado a "+cHostName+"("+cIP+")" ) }
oSocket:bClose = { || MsgInfo( "Servidor inativado!" ) }
//syswait(3)
oSocket:Connect( cIP )
//
//oSocket:bAccept = { | oSocket | oServer := TSocket():Accept( oSocket:nSocket ),;
// oServer:Cargo := ST_COMMAND,;
// oServer:bRead := { | oSocket | OnRead( oSocket ) } }
//oSocket:Listen()
return nil
//------------------------------------------------------------------------//
function OnRead( oSocket )
local cData := oSocket:GetData()
local cToken
do case
case oSocket:Cargo == ST_COMMAND
cToken = StrToken( cData, 1 )
do case
case cToken == "SENDCMD"
if "NOFOUND" $ SubStr( cData, 8 )
MsgWait( "Nao encontrado " + SubStr( cData, 8 ) )
// oWnd:End()
endif
case cToken == "MSG"
MsgInfo( SubStr( cData, 5 ) )
endcase
case oSocket:Cargo == ST_SENDFILE
fwrite( oSocket:hFile, cData, Len( cData ) )
LogFile( "sockserv.txt", { "writting..." } )
if Len( cData ) < FILE_BLOCK
// fclose( oSocket:hFile )
// MsgInfo( Len( cData ) )
// oSocket:Cargo = ST_COMMAND
endif
endcase
return nil
//------------------------------------------------------------------------//
function getIPExtern( _site_ )
local _IPExtern_
ws:=TdWebService():new()
_IPExtern_ := ws:OpenWS( _site_ )
ws:end()
return _IPExtern_
//------------------------------------------------------------------------//
function SendSEARCH()
//
cCMDString := space(40)
MsgGet( "Pesquisar", "Nome", @cCMDString )
oSocket:SendData( "SENDSEARCH " + cCMDString )
//
return nil
//------------------------------------------------------------------------//
function SendCMD( cCMDString )
//
oSocket:SendData( "SENDCMD " + cCMDString )
//
return nil
//------------------------------------------------------------------------//
function SendData()
cREGString := "00246|JOSE CARLOS DA ROCHA|(011)3534-3099|ROCHINHA"
//
oSocket:SendData( "SENDDATA " + cREGString )
//
return nil
//------------------------------------------------------------------------//
function SaveData()
cREGString := "00246|JOSE CARLOS DA ROCHA|(011)3534-3099|ROCHINHA"
//
oSocket:SendData( "SAVEDATA " + cREGString )
//
return nil
//------------------------------------------------------------------------//
function SendFile()
local cFileName := cGetFile( "*.*", "Select a file to send by Internet" )
if ! Empty( cFileName ) .and. File( cFileName )
oSocket:SendData( "SENDFILE " + cFileName( cFileName ) )
oSocket:SendFile( cFileName )
oSocket:End()
MsgInfo( "File sent" )
endif
return nil
//------------------------------------------------------------------------//
function VerifyINI( _section_, _entry_, _var_, _inifile_, _grava_ )
oIni := TIni():New( _inifile_ )
if _grava_ = .t.
oIni:Set( _section_, _entry_, _var_ )
endif
return oIni:Get( _section_, _entry_, _var_, _var_ )
/*
******
* Classe de acesso a webservice
******
*/
CLASS TdWebService
DATA hOpen
DATA sbuffer HIDDEN
DATA xDLL HIDDEN
METHOD New(buffersize) CONSTRUCTOR
METHOD OpenWS(url)
METHOD End()
ENDCLASS
METHOD New(conexion,buffersize) CLASS TdWebService
DEFAULT buffersize:=64000
::sbuffer:=buffersize
xDll:=LoadLib32("wininet.dll")
::hOpen = InternetOpen("TdWebService", 1,,, 0)
RETURN Self
METHOD OpenWS(url) CLASS TdWebService
local hFile,ret,xml
hFile = InternetOpenUrl(::hOpen, url,"",0,,0)
xml:=space(::sbuffer)
InternetReadFile(hFile, @xml, ::sbuffer, @Ret)
return subst(alltrim(xml),1,len(alltrim(xml)))
METHOD End() CLASS TdWebService
FreeLib32(xDll)
return nil
/*
******
* Funcoes de socket
******
*/
DLL32 FUNCTION InternetOpen( cApp as LPSTR, n1 AS DWORD, n2 AS LPSTR, n3 AS LPSTR, n4 AS DWORD ) AS LONG PASCAL FROM "InternetOpenA" LIB xDll
Dll32 FUNCTION InternetReadFile(hFile As 7, @sBuffer As 8, lNumBytesToRead As 7, @lNumberOfBytesRead As 7) As 7 PASCAL Lib xDll
Dll32 FUNCTION InternetOpenUrl(hInternetSession As 7, lpszUrl As 8, lpszHeaders As 8, dwHeadersLength As 7, dwFlags As 7, dwContext As 7) As 7 FROM "InternetOpenUrlA" PASCAL Lib xDll
DLL32 FUNCTION InternetCloseHandle( hSession AS LONG ) AS BOOL PASCAL LIB xDll
DLL32 FUNCTION InternetConnect( hInternet AS LONG, cServerName AS LPSTR, nServerPort AS LONG, cUserName AS LPSTR, cPassword AS LPSTR, nService AS DWORD, nFlags AS DWORD, @nContext AS PTR ) AS LONG PASCAL FROM "InternetConnectA" LIB xDll
DLL32 FUNCTION FTPGETFILE( hConnect AS LONG, cRemoteFile AS LPSTR, cNewFile AS LPSTR, nFailIfExists AS LONG, nFlagsAndAttribs AS DWORD, nFlags AS DWORD, @nContext AS PTR ) AS BOOL PASCAL FROM "FtpGetFileA" LIB xDll
DLL32 FUNCTION FTPPUTFILE( hConnect AS LONG, cLocalFile AS LPSTR, cNewRemoteFile AS LPSTR, nFlags AS DWORD, @nContext AS PTR ) AS BOOL PASCAL FROM "FtpPutFileA" LIB xDll
DLL32 FUNCTION InternetWriteFile( hFile AS LONG, cBuffer AS LPSTR, lSize AS LONG, @nSize AS PTR ) AS BOOL PASCAL LIB xDll
DLL32 FUNCTION FtpOpenFile( hFTP AS LONG, cRemoteFile AS LPSTR, n1 AS LONG, n2 AS LONG, n3 AS LONG ) AS LONG PASCAL FROM "FtpOpenFileA" LIB xDll
DLL32 FUNCTION InternetSetFilePointer( hFile AS LONG, nDistanceToMove AS LONG, nReserved AS LPSTR, nSeekMethod AS LONG, @nContext AS PTR ) AS BOOL PASCAL LIB xDll
DLL32 FUNCTION FtpFindFirstFile( hFTP AS LONG, cMask AS LPSTR, @cWin32DataInfo AS LPSTR, n1 AS LONG, n2 AS LONG ) AS LONG PASCAL FROM "FtpFindFirstFileA" LIB xDll
DLL32 FUNCTION InternetFindNextFile( hFTPDir AS LONG, @cWin32DataInfo AS LPSTR ) AS BOOL PASCAL FROM "InternetFindNextFileA" LIB xDll
SOC2SERV.PRG
// Socket server connection sample
#include "FiveWin.ch"
#define ST_COMMAND 1
#define ST_SENDFILE 2
#define FILE_BLOCK 8000
static oWnd, oSocket, oClient
//------------------------------------------------------------------------//
function Main()
local oBar
// **********************************************************************
cPath := cFilePath( GetModuleFileName( GetInstance() ) )
// Pega nome da maquina
cNetName := NETNAME()
// Pega IP da maquina
WsaStartUp(); cHostName := getHostByName( cNetName ); WsaCleanUp()
// Salva dados
VerifyINI( "SOCKSERV", "NAME", cNetName , cPath+"soc2serv.ini", .T. )
VerifyINI( "SOCKSERV", "IP" , cHostName, cPath+"soc2serv.ini", .T. )
// **********************************************************************
if ! file( "SOCKSERV.DBF" )
ESTRU_DBF := { { "IDCODIGO" , "N", 5, 0 } , ;
{ "NOME" , "C",40, 0 } , ;
{ "TELEFONE" , "C",14, 4 } , ;
{ "CONTATO" , "C",20, 0 } }
DBCREATE( "SOCKSERV", ESTRU_DBF )
endif
// **********************************************************************
DEFINE WINDOW oWnd TITLE "Servidor: " + cNetName
DEFINE BUTTONBAR oBar OF oWnd _3D
DEFINE BUTTON OF oBar ACTION Server() TOOLTIP "Listen"
ACTIVATE WINDOW oWnd ON INIT Server()
return nil
//------------------------------------------------------------------------//
function Server()
oSocket = TSocket():New( 2000 )
oSocket:bAccept = { | oSocket | oClient := TSocket():Accept( oSocket:nSocket ),;
oClient:Cargo := ST_COMMAND,;
oClient:bRead := { | oSocket | OnRead( oSocket ) },;
oClient:bClose := { | oSocket | OnClose( oSocket ) } }
oSocket:Listen()
return nil
//------------------------------------------------------------------------//
function OnRead( oSocket )
local cData := oSocket:GetData()
local cToken
LogFile( "soc2serv.txt", { Len( cData ) } )
do case
case oSocket:Cargo == ST_COMMAND
cToken = StrToken( cData, 1 )
do case
case cToken == "SENDCMD"
if "QUIT" $ SubStr( cData, 8 )
MsgWait( "Fechando Aplicativo" )
oWnd:End()
endif
case cToken == "MSG"
MsgRun( SubStr( cData, 5 ) )
case cToken == "SENDSEARCH"
cNome := upper( alltrim( substr( cData, 12 ) ) )
//if ! file( "sockserv.dbf" )
USE sockserv SHARED
locate for alltrim(upper(cNome)) $ alltrim(upper(sockserv->nome))
if found()
? "Encontrei:",sockserv->nome,"Registro:",recno(),"Telefone:",sockserv->telefone
else
? "nao encontrei "+cNome
endif
BROWSE()
USE
MsgRun( "Inserido "+cData )
//else
// MsgRun( "Arquivo de suporte nao foi criado." )
//endif
case cToken == "SAVEDATA"
aSockServ := StringToArray( SubStr( cData, 10 ), "|" )
//if ! file( "sockserv.dbf" ) // .and. ! len( aSockServ )=0
//
USE sockserv SHARED
dbAppend()
sockserv->IDCODIGO := recco()+1 // val( aSockServ[1] )
sockserv->NOME := aSockServ[2]
sockserv->TELEFONE := aSockServ[3]
sockserv->CONTATO := aSockServ[4]
dbCommit()
USE
MsgRun( "Inserido "+cData )
//else
// MsgRun( "Arquivo de suporte nao foi criado." )
//endif
case cToken == "SENDDATA"
aSockServ := StringToArray( SubStr( cData, 10 ), "|" )
//if ! file( "sockserv.dbf" ) // .and. ! len( aSockServ )=0
aPrimeiroNome := {"JOSE","JOAO","ANTONIO","MARIA","CATIA","MARIANA"}
aSegundoNome := {"CARLOS","MARCOS","PIRES","FLAVIO","HENRIQUE","VAGNER"}
aSobreNome := {"DA SILVA","DA COSTA","DOS ANJOS","DOS SANTOS","DE MOURA","DE PAULA"}
//
cSSNome := aPrimeiroNome[Random(6)] + " " + aSegundoNome[Random(6)] + " " + aSobreNome[Random(6)]
//
USE sockserv SHARED
dbAppend()
sockserv->IDCODIGO := recco()+1 // val( aSockServ[1] )
sockserv->NOME := cSSNome // aSockServ[2]
sockserv->TELEFONE := aSockServ[3]
sockserv->CONTATO := aSockServ[4]
dbCommit()
USE
MsgRun( "Inserido "+cData )
//else
// MsgRun( "Arquivo de suporte nao foi criado." )
//endif
endcase
case oSocket:Cargo == ST_SENDFILE
fwrite( oSocket:hFile, cData, Len( cData ) )
LogFile( "sockserv.txt", { "writting..." } )
if Len( cData ) < FILE_BLOCK
// fclose( oSocket:hFile )
// MsgInfo( Len( cData ) )
// oSocket:Cargo = ST_COMMAND
endif
endcase
return nil
//------------------------------------------------------------------------//
function OnClose( oSocket )
MsgRun( "Client has closed!" )
do case
case oSocket:Cargo == ST_SENDFILE
fclose( oSocket:hFile )
endcase
oSocket:End()
return nil
//------------------------------------------------------------------------//
function VerifyINI( _section_, _entry_, _var_, _inifile_, _grava_ )
oIni := TIni():New( _inifile_ )
if _grava_ = .t.
oIni:Set( _section_, _entry_, _var_ )
endif
return oIni:Get( _section_, _entry_, _var_, _var_ )
//------------------------------------------------------------------------//
function StringToArray( cString, cSeparator )
LOCAL nPos
LOCAL aString := {}
DEFAULT cSeparator := ";"
cString := ALLTRIM( cString ) + cSeparator
DO WHILE .T.
nPos := AT( cSeparator, cString )
IF nPos = 0
EXIT
ENDIF
AADD( aString, SUBSTR( cString, 1, nPos-1 ) )
cString := SUBSTR( cString, nPos+1 )
ENDDO
RETURN ( aString )
//------------------------------------------------------------------------//
function ArrayToString( aArray, cSeparator )
LOCAL nPos
DEFAULT cSeparator := ";"
cString := ""
FOR nPos = 1 TO LEN(aArray)
cString := cString + aArray[nPos] + cSeparator
NEXT
RETURN ( cString )
//------------------------------------------------------------------------//
function Random( nMaximo )
static nRandom
local nTemporal
nMaximo = if( nMaximo == NIL, 65535, nMaximo )
if nRandom == NIL
nRandom = seconds()
endif
nTemporal = ( nRandom * seconds() ) % ( nMaximo + 1 )
nTemporal = if( nTemporal < 1, 1, nTemporal )
nRandom = nTemporal + seconds()
RETURN int( nTemporal )
SOC2TESTE.RAR