La magia de los Sockets

User avatar
Busmatic_wpb
Posts: 162
Joined: Wed Feb 22, 2017 2:19 am

La magia de los Sockets

Post by Busmatic_wpb »

Estimados Listeros.

Gracias a mi amigo Venesolano Sr. Albeiro Valencia que me ha ayudado a desarrollar un aplicacion de coneccion por la clase sockets, al final trabajo de maravillas , le hemos metido mano a la clase se han hecho grandes cosas. Hemos logrado comunicarnos los equipos (coches) que tengo en carretera a un server estacionario en un 100% sin errores y comandos to envio de informarcion de los clientes al server grabando en tablas Mysql con Dolphin y trabaja de muy bien .

Tambien hemos logrado enviar comandos de Servidor a cliente y viceverza y la verdad he quedado atonito ver el poder rapidez con que esta cosa trabaja la clase.

Ya montamos un arreglo de clientes que nos ayuda a mandar mensajes o peticiociones de informacion a uno a todos clientes..

Hemos logrado enviar strings de mas de 100 caracteres y ni cuenta se da el programa TAkilla- cliente que esta montado en un table windows 10 con fivewin que se comporta al 100% , utilzamos un timer para cada minuto madar el string al servidor, les comento esto porque he visto mucho comentarios acerca de esta calse
y queria compartir mis impresiones.

Vean ustedes que bonito

Ejemplo sockets



Albeiro Valencia
albeiroval@gmail.com

_ Chacon.
http://www.busmaticcr.com


Ejemplo sockets

Image

Ahore miren la informacion descargada por CLiente..

Image
Last edited by Busmatic_wpb on Wed May 16, 2018 3:52 am, edited 3 times in total.
Regards.
S.I.T.U.
Sistemas Inteligentes de transporte urbano
http://www.situcr.com
_@Situcr.com
Desarrollos BA4/B4j androide
User avatar
albeiroval
Posts: 323
Joined: Tue Oct 16, 2007 5:51 pm
Location: Barquisimeto - Venezuela

Re: La magia de los Sockets

Post by albeiroval »

_,

Muchas gracias por tus palabras, para mi es un placer haber podido colaborar con este proyecto.
Saludos,
Regards,

Albeiro Valencia
www.avcsistemas.com
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: La magia de los Sockets

Post by Antonio Linares »

Estimados _ y Albeiro,

¿ Podríais publicar un ejemplo de cómo lo habéis hecho para ayudar a otros usuarios ?

Muchas gracias
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
jose_murugosa
Posts: 943
Joined: Mon Feb 06, 2006 4:28 pm
Location: Uruguay
Contact:

Re: La magia de los Sockets

Post by jose_murugosa »

Fascinante, lo que relatas lo es realmente, de verdad sería buenísimo que compartieras un ejemplo sobre como usas sockets con nosotros.
Saludos/Regards,
José Murugosa
FWH + Harbour + Bcc7. Una seda!
User avatar
Busmatic_wpb
Posts: 162
Joined: Wed Feb 22, 2017 2:19 am

Re: La magia de los Sockets

Post by Busmatic_wpb »

Saludes,

Con mucho gusto haremos una copia del desarrollo, del servidor de sockets y Cliente el compañero Albeiro, el hizo cambios sustanciales y mejoras para ajustarla a mis necesitades y ponerla andar. Les comento que esta rutina trabaja exelente libre de errores fue modificada de la rutina original de FW / Autor : Antonio Linares .
y prontamente se publicara al Server/Cliente con _ hechos y ajustes.

_ Chacon
http://www.SITU.com
Last edited by Busmatic_wpb on Mon May 21, 2018 5:53 am, edited 5 times in total.
Regards.
S.I.T.U.
Sistemas Inteligentes de transporte urbano
http://www.situcr.com
_@Situcr.com
Desarrollos BA4/B4j androide
hmpaquito
Posts: 1200
Joined: Thu Oct 30, 2008 2:37 pm

Re: La magia de los Sockets

Post by hmpaquito »

Gracias por el aporte a la comunidad.

Dios te bendiga.
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: La magia de los Sockets

Post by Antonio Linares »

Estimado Albeiro,

Revisando el código de _, parece que el servidor es un trabajo derivativo del ejemplo sockserv.prg de FWH

¿ Podrías publicar _ y mejoras realizadas ?

gracias
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Busmatic_wpb
Posts: 162
Joined: Wed Feb 22, 2017 2:19 am

Re: La magia de los Sockets

Post by Busmatic_wpb »

Estimado Linares.
Con mucho gusto publicaremos socket server /cliente y sus modificaciones protamente apenas terminemos de hacer los ultimos ajustes segun me comunico el Sr. Valencia

_ Chacon.
Last edited by Busmatic_wpb on Mon May 21, 2018 5:49 am, edited 1 time in total.
Regards.
S.I.T.U.
Sistemas Inteligentes de transporte urbano
http://www.situcr.com
_@Situcr.com
Desarrollos BA4/B4j androide
User avatar
albeiroval
Posts: 323
Joined: Tue Oct 16, 2007 5:51 pm
Location: Barquisimeto - Venezuela

Re: La magia de los Sockets

Post by albeiroval »

Estimado Antonio,

A continuacion agrego el codigo servidor y cliente para manejo de sockets que usa _ Chacon en su aplicacion de control
sistematizado de monitoreo de coches en tiempo real, el cual es una maravilla.

Codigo Server :

Code: Select all

#include "FiveWin.ch"
#include "FileI.ch"
#include "TSocket.ch"
#include "C:\dolphin\include\tdolphin.ch"

#define ST_COMMAND  1
#define ST_SENDFILE 2
#define FILE_BLOCK 8000

//-------------------------------------------//

static h
static oSocket
static oClient

//-------------------------------------------//

Function Main2()
  Local oBar
  Local aConexion := { { 0, "S/N", "FECHA", "HORA"  } }

  h := Hash()

  h["cFileTxt"] := "monitor_avl.txt"
  h["lListen" ] := .F.
  h["cTable"  ] := "monitoravl"
  h["aClient" ] := {}

  SET DELETED           ON
  SET CASESENSITIVE     ON
  SET PADRIGHT           ON
  SET LOGICALVALUE      ON

  h["oSrv"] := TSituMySQL():New( "localhost", "root", "pampa36", "situ" )
  
  if h["oSrv"]:lConnect
     ValidaTabla( h["cTable"] )
  endif

  if !File( h["cFileTxt"] )
     h["hFile"] := FCreate( h["cFileTxt"], FC_NORMAL )
  endif

  h["hFile"] := FOpen( h["cFileTxt"], FO_READWRITE + FO_SHARED )
  
  DEFINE WINDOW h["oWnd"] TITLE "Servidor : "

  @200,600 BTNBMP oBtn1 OF h["oWnd"] ;
    SIZE 500,300 PIXEL ;
    RESOURCE "#8002" ;
    TOP NOBORDER
    
  oBtn1:lTransparent = .t.
  oBtn1:cToolTip = { "Busmatic de CR" + CRLF + "Ing: _ Chacon","Todos los derechos reservados "+str(year(date())), 1, CLR_BLACK, 14089979 }
  oBtn1:SetColor( 0, )

  DEFINE BUTTONBAR oBar OF h["oWnd"] 2015 SIZE 70, 70

   DEFINE BUTTON OF oBar;
      CENTER;
      PROMPT "Conectar"  ;
      ACTION if(!h["lListen"],  Server(), MsgStop("Server ya esta Activo") );
       FILE "BMP\conecta.png";
      TOOLTIP "Conectar"

   DEFINE BUTTON OF oBar;
      CENTER;
      PROMPT "Send Data";
      ACTION  EnvioCom( );
      FILE "BMP\todos.png";
      TOOLTIP "Actulizar tarifas";
      GROUP

   DEFINE BUTTON OF oBar;
      CENTER;
      PROMPT "Send MSG";
      ACTION  EnvioMensa();
      FILE "BMP\todosuser .png";
      TOOLTIP "Enviar mensajes a todos  ";
      GROUP

   DEFINE BUTTON OF oBar;
      CENTER;
      PROMPT "Desconecta";
      ACTION ( OnClose( oSocket ), h["oWnd"]:End() );
      TOOLTIP "Exit";
      FILE "BMP\STOP.png";
      GROUP

   @ 6, 6 XBROWSE h["oBrw"] OF h["oWnd"];
         DATASOURCE aConexion;
         COLUMNS 1,2,3,4;
         HEADERS "Id", "Placa", "Fecha", "Hora";
         FOOTERS;
         SIZE 360, 600

         h["oBrw"]:nMarqueeStyle    := MARQSTYLE_HIGHLROW
         h["oBrw"]:nHeaderLines        := 1
         h["oBrw"]:lColDividerComplete := .T.
         h["oBrw"]:cToolTip :=  'Desglose de movimimientos'

         h["oBrw"]:nColDividerStyle    := 1
         h["oBrw"]:lHScroll            := .T.
         h["oBrw"]:lfastedit := .f.
         h["oBrw"]:lAllowRowSizing  := .T.
         h["oBrw"]:nHeaderLines        := 1
         h["oBrw"]:nFooterLines        := 0
         h["oBrw"]:nDataLines          := 3
         h["oBrw"]:lFooter             := .f.
         h["oBrw"]:nRowHeight :=30

         h["oBrw"]:lFastEdit := .F.
         h["oBrw"]:SetBackGround( "BMP\fondo2.png", BCK_FILL )

         h["oBrw"]:lKinetic      := .T.
         h["oBrw"]:lContrastClr  := .T.  //para que no cambie color de texto automaticamente segun intensidad del fondo
         h["oBrw"]:lColChangeNotify := .t.  // bChange evalua cambio de columna y permite tomar una accion
         h["oBrw"]:lCanPaste  := .t.   //copiar/pegar datos entre columnas

         WITH OBJECT h["oBrw"]
             :SetGroupHeader( ' ID ' + CRLF + 'Asigdos',    1,1 )
             :SetGroupHeader( 'COCHES ' + CRLF + 'CONECTADOS',2,4)
         END

     WITH OBJECT h["oBrw"]
         h["oBrw"]:aCols[ 1 ]:cHeader  = "CONECTA"
         h["oBrw"]:aCols[ 1 ]:nWidth   = 60
         h["oBrw"]:aCols[ 1 ]:nHeadStrAlign := AL_CENTER
         h["oBrw"]:aCols[ 1 ]:nDataStrAlign := AL_CENTER
      END

      WITH OBJECT h["oBrw"]
         h["oBrw"]:aCols[ 2 ]:cHeader  = "Coche"
         h["oBrw"]:aCols[ 2 ]:nWidth   = 100
         h["oBrw"]:aCols[ 2 ]:nHeadStrAlign := AL_CENTER
         h["oBrw"]:aCols[ 2 ]:nDataStrAlign := AL_CENTER
      END

      WITH OBJECT h["oBrw"]
         h["oBrw"]:aCols[ 3 ]:cHeader  = "Fecha"
         h["oBrw"]:aCols[ 3 ]:nWidth   = 75
         h["oBrw"]:aCols[ 3 ]:nHeadStrAlign := AL_CENTER
         h["oBrw"]:aCols[ 3 ]:nDataStrAlign := AL_CENTER
      END

       WITH OBJECT h["oBrw"]
         h["oBrw"]:aCols[ 4 ]:cHeader  = "Hora"
         h["oBrw"]:aCols[ 4 ]:nWidth   = 100
         h["oBrw"]:aCols[ 4 ]:nHeadStrAlign := AL_CENTER
         h["oBrw"]:aCols[ 4 ]:nDataStrAlign := AL_CENTER
      END

   h["oBrw"]:CreateFromCode()

   ACTIVATE WINDOW h["oWnd"] ;
        MAXIMIZED;
      ON INIT Server()  

   FClose( h["hFile"] )

   h["oSrv"]:Close()

Return Nil

//-------------------------------------------//

static Function Server()

  if oSocket != NIL
     oSocket:End()
  endif

  oSocket = TSocket():New( TSOCK_SRV, 5000, "soc2serv.ini" )

  oSocket:bAccept = ;
                            <| oSocket |
                    oClient := TSocket():Accept( oSocket:nSocket )
                  AAdd( h["aClient"], oClient:nSocket )
                  oClient:Cargo  := ST_COMMAND
                  oClient:bRead  := { | oSocket | OnRead( oSocket ) }
                  oClient:bClose := { | oSocket | OnClose( oSocket ) }
                  oClient:SendData( "ok" )
                                    Return Nil
                >

  oSocket:Listen()
  
  h["oWnd"]:SetText( "Servidor : (" + oSocket:cIPAddr + ")" )

  h["lListen"] := .T.

Return Nil

//-------------------------------------------//

static Function OnRead( oSocket )
    Local aSockServ
  Local cToken
  Local aFirstName
  Local aSecondName
  Local aAliasName
  Local cName
  Local cSSNome
  Local cMsg
  Local cData := oSocket:GetData()

  do case

  case oSocket:Cargo == ST_COMMAND
    cToken = StrToken( cData, 1 )

    do case

    case cToken == "SEND-BRW"
        cMsg := SubStr( cData, 10 )
      UpdateBrowse( cMsg )

    case cToken == "SENDCMD"
       if "QUIT" $ SubStr( cData, 8 )
          LogFile( "socket_server.txt",  "Close Server !!!" )
          MsgWait( "Close Server !!!" )
         h["oWnd"]:End()
      endif

    case cToken == "MSG"
      cMsg := SubStr( cData, 5 )
      AddLineMonitor( cData )
      // MsgRun( cMsg )

    endcase

  case oSocket:Cargo == ST_SENDFILE
     fwrite( oSocket:h["hFile"], cData, Len( cData ) )
     LogFile( "socket_server.txt", { "writting..." } )
     
     if Len( cData ) < FILE_BLOCK
        // fclose( oSocket:h["hFile"] )
       // MsgInfo( Len( cData ) )
       // oSocket:Cargo = ST_COMMAND
     endif

   endcase

Return Nil

//-------------------------------------------//

static Function OnClose( oSocket )

  // MsgRun( "Client has closed!" )

  //  ? oSocket:nSocket

   if oSocket != Nil

      DeleteItem( oSocket:nSocket )

      do case

      case oSocket:Cargo == ST_SENDFILE
         fclose( oSocket:h["hFile"] )

      endcase

      oSocket:End()

   endif

Return Nil

//-------------------------------------------//

static Function AddLineMonitor( cTexto )
   Local o := TFBuffer():new( h["hFile"] )

  o:addString( cTexto )
  o:free()

  Desglose( cTexto)

Return Nil

//-------------------------------------------//

Function Desglose(cTexto)

   Local dOpusuario   := substr(cTexto,5,4)
   Local dFecha       := substr(cTexto,9,10)
   Local dHora         := substr(cTexto,19,8)
   Local dPlacas      := substr(cTexto,27,13)
   Local dchoferNom   := substr(cTexto,40,13)
   Local dultParada   := substr(cTexto,53,25)
   Local dlati         := substr(cTexto,78,14)
   Local dlong         := substr(cTexto,92,14)
   Local dSpeed         := VAL(substr(cTexto,106,6))
   Local dSindescar   := VAL(substr(cTexto,112,5))
   Local INI001         := AT("£",cTexto)
   Local INI002         := AT("Ø",cTexto)-1
   Local INI003         := AT("ƒ",cTexto)
   Local INI004         := AT("á",cTexto)-1
   Local dInter         := substr(cTexto,INI001+1,abs(INI001-INI002))
   Local dExter         := substr(cTexto,INI003+1,abs(INI003-INI004))
   Local Data13       := ""

    Local INI005:=AT("¦",cTexto)-1
   Local dvsw  :=substr(cTexto,INI005+2,9)

   Local INI006 := AT("¢",cTexto)-1
   Local dtarver:= substr(cTexto,INI006+2,19)

   Local INI0016:=AT("§",cTexto)
   Local dbarras:= substr(cTexto,INI0016+1,1)

   Local INI0017:=AT("³",cTexto)
   Local dgps:= substr(cTexto,INI0017+1,1)

   Local INI0018:=AT("¨",cTexto)
   Local Lsc:= substr(cTexto,INI0018+1,1)

   Local INI0019:=AT("²",cTexto)
   Local EstMaq:= substr(cTexto,INI0019+1,2)

   Local INI0020:=AT("å",cTexto)
   Local Estqui:= substr(cTexto,INI0020+1,2)



   Local INI0020a:=AT("|",cTexto)

   LocaL INI0021:=substr(cTexto,INI0020a+1,2)

   Local Lineas:=substr(cTexto,INI0020a+3,val(INI0021))

   Local INI0022:=AT("Ô",cTexto)
   Local Sent:= substr(cTexto,INI0022+1,3)

   Local INI0023:=AT("Ç",cTexto)
   Local Horas:= substr(cTexto,INI0023+1,5)

   Local NueVPa:=alltrim( STRTRAN(dultParada, "0", " "))
   Local Nuevapla:=alltrim( STRTRAN(dPlacas, "0", " "))


   aColumnas := {"placa", "chofer", "versionsw", "latitud", "longitud", "barras", "gps", "lector", "ultimaparada", "speed", ;
    "estadocomdo", "estadoequipo", "carrerasopen", "mensajes", "horaservicio",;
    "lineaservicio", "sentidoservicio", "pasajeroservicio", "fecha", "hora", "carreraspend", "iplocal", "ipext", "versiontar" }



   aValues   := {  Nuevapla,dOpusuario,dvsw,dlati,dLong, dbarras,dgps, Lsc, NueVPa,dSpeed, EstMaq,Estqui,0,"mens", Horas,Lineas,Sent,;
                   0,date() ,dhora ,dSindescar, dInter,dExter, dtarver}


   LoadServer( aColumnas, aValues, h["cTable"] )

   UpdateBrowse( Nuevapla )


return nil

//-------------------------------------------//

Function LoadServer(aColumnas, aValues,cTable)

  if h["oSrv"]:lConnect
      h["oSrv"]:InsertRow( cTable,  aColumnas, aValues )
   endif

   return NIl


//-------------------------------------------//

static Function ValidaTabla( cTable )
   Local cStruct

   TEXT INTO cStruct
     CREATE TABLE IF NOT EXISTS %1
     (   placa               CHAR(13) default ' ' ,
         chofer              CHAR(13) default ' ' ,
         versionsw           CHAR(13) default ' ' ,
         latitud             CHAR(15)  ,
         longitud            CHAR(15)  ,
         barras              CHAR(1)   ,
         gps                 CHAR(1)   ,
         lector              CHAR(1)   ,
         ultimaparada        CHAR(25)  ,
         speed               DECIMAL(5,2)   ,
         estadocomdo         CHAR(3)   ,
         estadoequipo        CHAR(3)  ,
         carrerasopen        INT   ,
         mensajes            TEXT      ,
         horaservicio        CHAR(5)  ,
         lineaservicio       CHAR(25)  ,
         sentidoservicio     CHAR(3)  ,
         pasajeroservicio    CHAR(5)  ,
         fecha               DATE  ,
         hora                CHAR(10)  ,
         carreraspend        INT  ,
         iplocal             CHAR(15) ,
         ipext               CHAR(15)  ,
         versiontar          CHAR(20)  ,
         versiontsw          CHAR(20)  ,
         auto                    INT NOT NULL AUTO_INCREMENT,
         INDEX (placa, chofer ),
         PRIMARY KEY (auto)
     ) COLLATE = 'latin1_spanish_ci' ENGINE = InnoDB
  ENDTEXT

  // latin1_spanish_ci
  // CASE SENSITIVE (diferencia entre mayuscula y minisculas)
  // CASE INSENSITIVE (no diferencia)

  cStruct := StrFormat( cStruct, cTable )

  h["oSrv"]:VerifyTable( cTable, cStruct )

Return Nil

//-------------------------------------------//

static Function UpdateBrowse( cData )
   Local aArray   := h["oBrw"]:aArrayData
   Local nIdClien := ATail( h["aClient"] )
   Local nPos

   nPos := AScan( aArray, {|a| a[1] == nIdClien } )

   If nPos==0
      AAdd( aArray, { nIdClien, cData, Date(), Time() } )
      h["oBrw"]:SetArray( aArray )
      h["oBrw"]:Refresh()
   endif

return Nil

//-------------------------------------------//

static Function DeleteItem( nIdClien )
   Local nPos
   Local aArray := h["oBrw"]:aArrayData

   nPos := AScan( aArray, {|a| a[1] == nIdClien } )
   if nPos > 0
       ADel( aArray, nPos, .T. )
     //  MsgInfo("Registro Borrado")
   endif

   h["oBrw"]:SetArray( aArray )
   h["oBrw"]:Refresh()

return Nil

//-------------------------------------------//

Static Function EnvioCom()
   Local comandos:="COM:DESTAR"
   oClient:SendData(  comandos )
return NIl

//-------------------------------------------//

static Function EnvioMensa()

   Local cCmdStr := Space(40)
   Local comandos:="COM:MENSA"

   MsgGet( "Mensaje", "Enviar : ", @cCmdStr )

   if !Empty( cCmdStr )
      Mensaje:= comandos+cCmdStr
      oClient:SendData(Mensaje )
  endif

Return Nil

 
Codigo Cliente :

Code: Select all

#include "FiveWin.ch"
#include "TSocket.ch"

#define ST_COMMAND  1
#define ST_SENDFILE 2
#define FILE_BLOCK 8000

static oSocket

//-----------------------------------------//

Function MainSocket()

  if oSocket != NIL
     oSocket:End()
  endif

   oSocket = TSocket():New( TSOCK_CLI, 5000, "soc2cli.ini" )  

   oSocket:bRead    = { | oSocket | HandleRecived( oSocket ) }

   // oSocket:bConnect = { || MsgInfo( "Conectado !!!" ) ) }
  //  oSocket:bClose   = { || MsgInfo( "Servidor Inactivo !!!" ) }

  oSocket:Connect()

Return Nil

//-------------------------------------------//

static Function HandleRecived( oSocket )
    Local cData := oSocket:GetData()

        if cData = "ok"
        LogFile( "socket_server.txt", "Connected !!" )
        else
        // MSGWait("No conecto server Fail",1)
          // LogFile( "socket_server.txt", "Fallo coneccion "+ cData )
          // Return nil
     endif

        If alltrim(cData)=="COM:DESTAR"
       // revisar el estado de las tarifas en el server local

       FuerzaTarifas()

    elseif substr(cData,1,9) =="COM:MENSA"
    
       SndPlaySound(".\SOUND\mensaje01.WAV")
       GrabarMEnsajes(cData)
       elseif alltrim(cData)==""
       elseif alltrim(cData)==""

    Endif

Return nil

//-------------------------------------------//

Function SendMsg(cMsg)
   Local lSucess :=.T.

// Local cMsg :=  Space(40)
// MsgGet( "Send Message", "Message : ", @cMsg )

   if !Empty( cMsg )
      oSocket:SendData( "MSG " + cMsg )
   endif

Return lSucess

 
Tome como referencia los ejemplos de sockserv.prg y sockcli.prg de FWH.
Last edited by albeiroval on Mon May 21, 2018 2:41 pm, edited 1 time in total.
Saludos,
Regards,

Albeiro Valencia
www.avcsistemas.com
User avatar
Busmatic_wpb
Posts: 162
Joined: Wed Feb 22, 2017 2:19 am

Re: La magia de los Sockets

Post by Busmatic_wpb »

Muchas gracias compañero Albiero Valencia
Se le agaracede por sus aportes , te comento que la implentacion fue cero errores , muy eficiente y rapido, muchas gracias.
Atentamente.

_ Chacon.
www.Situ.com
Regards.
S.I.T.U.
Sistemas Inteligentes de transporte urbano
http://www.situcr.com
_@Situcr.com
Desarrollos BA4/B4j androide
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: La magia de los Sockets

Post by Antonio Linares »

Muchas gracias :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
cnavarro
Posts: 5792
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: La magia de los Sockets

Post by cnavarro »

Otro ejemplo distinto de uso de Sockets ( una curiosidad ), basado también el los ejemplos de samples
En este caso, envías desde el servidor la informacion necesaria para crear en el cliente una ventana que tenemos pintada en el servidor.
Lógicamente, es un primer paso, ya que para poder implementar el pintado de los controles, etc, el tema se complica, teniendo que hacer uso para mejor implementación, de multihilos y sobre todo de mutex ( para proteger los valores de datas y variables, y poder realizar el pintado de la ventana convenientemente, bueno, asi es como lo entiendo yo ), pero quizás lo encontréis "curioso".
El array aOrders, lo que contiene, es el número de orden que tiene esa DATA en el array aDatas, o el valor que ha de tener el parámetro que he de pasar al método New de TWindow ( para entenderlo quizás mejor, ejecuta la instrucción Xbrowse( aDatas ) que aparece comentada y mira la definición del método New en la clase TWindow, aunque se me han ocurrido otras formas de hacerlo
Si alguien lo encuentra interesante y se anima, pues podemos seguir desarrollando cosillas
Funcionamiento:
1.- Ejecutar el programa servidor y pulsar sobre "Listen"
2.- Ejecutar el programa cliente y pulsar sobre "Connect"
3.- Puedes pulsar en ambos sobre los botones "Send" en el servidor "Test Msg" en el cliente para comprobar que están conectados
4.- Pulsar en el cliente sobre "Request Window", y aparecerá un mensaje en el servidor que enviará la información al cliente en el que se pintará la ventana.

Code: Select all

// Socket server connection sample

#include "FiveWin.ch"

#define ST_COMMAND  1
#define ST_SENDFILE 2
#define FILE_BLOCK 8000

static oWnd, oSocket, oClient
Static aDatas

static aSockets 
static aClients
static aPorts

//------------------------------------------------------------------------//

function Main()

   local oBar

   aPorts   := { 2000 }
   aSockets := Array( Len( aPorts ) )
   aClients := Array( Len( aPorts ) )

   DEFINE WINDOW oWnd TITLE "Server Socket"

   DEFINE BUTTONBAR oBar OF oWnd SIZE 60, 32

   DEFINE BUTTON OF oBar PROMPT "Listen" ACTION Server() TOOLTIP "Listen" GROUP ;
         WHEN Hb_IsNil( oSocket )

   DEFINE BUTTON OF oBar PROMPT "Send"   ACTION oClient:SendData( "Hello!" ) ;
      TOOLTIP "Talk to client" GROUP
   
   DEFINE BUTTON OF oBar PROMPT "Close" ACTION Cierra() TOOLTIP "Cierra" GROUP

   ACTIVATE WINDOW oWnd

return nil

//------------------------------------------------------------------------//

function Server()

   local x
   oSocket = TSocket():New( 2000 )

   oSocket:bAccept = { | oSock | oClient := TSocket():Accept( oSocket:nSocket ),;
                       oClient:Cargo := ST_COMMAND,;
                       oClient:bRead := { | oSock | OnRead( oSock ) },;
                       oClient:bClose := { | oSock | OnClose( oSock ) } }

   oSocket:Listen()

   
return nil

//------------------------------------------------------------------------//

Function Cierra()

   oSocket:End()

Return nil

//----------------------------------------------------------------------------//

function OnRead( oSocket )

   local cData := oSocket:GetData()
   local cToken

   LogFile( "sockserv.txt", { Len( cData ), cData } )

   do case
      case oSocket:Cargo == ST_COMMAND
           cToken = StrToken( cData, 1 )
           do case
              case cToken == "TWINDOW:"
                   ? "Sending TWindow"
                   oClient:SendData( "TWINDOW|" + MyDatas( oWnd ) )

              case cToken == "SENDFILE"
                   oSocket:Cargo = ST_SENDFILE
                   oSocket:hFile = fcreate( StrToken( cData, 2 ) )

              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 OnClose( oSocket )

   MsgInfo( "Client has closed!" )

   do case
      case oSocket:Cargo == ST_SENDFILE
           fclose( oSocket:hFile )
   endcase

   oSocket:End()

return nil

//------------------------------------------------------------------------//

Function MyDatas( oObj )

   local aOrders
   local aEnvio    := {}
   local x
   local cVar
   local nPosV     := 0
   local cCad      := ""
   local aDatas
   local cClase    := ""

   cClase   := oObj:ClassName()
   aDatas   := MObjData( oOBj, .T. )
   aOrders  := { 106, 96, 86, 102, 61, 104, 120, 110, 117, 135, nil, nil, 90, 89, ;
                 113, nil, nil, nil, nil, nil, .T., 91, 63, 93, 81 }
   //XBrowse( aDatas )
   For x = 1 to Len( aOrders )
      if hb_IsNil( aOrders[ x ] )
         AAdd( aEnvio, nil )
      else
         if Valtype( aOrders[ x ] ) == "N"
            AAdd( aEnvio, aDatas[ aOrders[ x ] ][ 3 ] )
         else
            AAdd( aEnvio, aOrders[ x ] )
         endif
      endif
      cCad    += cValToStr( ATail( aEnvio ) ) + if( x < Len( aOrders ), "|", "" )
   Next x

Return cCad

//----------------------------------------------------------------------------//

//----------------------------------------------------------------------------//
// From XBrowse function
//----------------------------------------------------------------------------//

Function MObjData( oObj, lValues )

   local n, v
   local aData     := AOData( oObj )
   DEFAULT lValues := .T.

   for n := 1 to Len( aData )
      TRY
         v  := OSend( oObj, aData[ n ] )
      CATCH
         v  := '<protected>'
      END
      if lValues
         aData[ n ]  := Lower( Left( aData[ n ], 1 ) ) + ;
                        SubStr( aData[ n ], 2 , 1 ) + ;
                        Lower( SubStr( aData[ n ], 3 ) )
         aData[ n ]  := { n, aData[ n ], v }
      endif
   next n

return aData

//----------------------------------------------------------------------------//
 
Ahora el cliente

Code: Select all


// Client: Socket server connection sample

#include "FiveWin.ch"

static oWnd, oSocket

function Main()

   local oBar

   DEFINE WINDOW oWnd TITLE "Client socket"

   DEFINE BUTTONBAR oBar OF oWnd SIZE 60, 32

   DEFINE BUTTON OF oBar PROMPT "Connect" GROUP ACTION Client() TOOLTIP "Connect" ;
      WHEN Hb_IsNil( oSocket )

   DEFINE BUTTON OF oBar PROMPT "Msg Test" GROUP ;
      ACTION oSocket:SendData( "MSG This is a test" ) ;
      TOOLTIP "Send data"

   DEFINE BUTTON OF oBar PROMPT "Request Window" GROUP ;
      ACTION ( oSocket:SendData( "TWINDOW: " ) ) ;
      TOOLTIP "Request Window"

   //DEFINE BUTTON OF oBar GROUP ;
   //   ACTION SendFile() TOOLTIP "Send file"

   DEFINE BUTTON OF oBar PROMPT "Close" GROUP ;
      ACTION oSocket:End() TOOLTIP "End Socket"

   ACTIVATE WINDOW oWnd

return nil

function Client()

   oSocket = TSocket():New( 2000 )

   oSocket:bRead    = { | oSocket | GetMsgFromServer( oSocket ) }

   // Never use a MsgInfo() here because it hangs Windows!!!
   oSocket:bConnect = { || oWnd:SetText( "Connected!" ) }

   oSocket:bClose   = { || MsgInfo( "Server has closed!" ) }

   oSocket:Connect( "127.0.0.1" ) // use the server IP address here   
   //oSocket:Connect( "192.168.1.10" )  // Internal IP
   //oSocket:Connect( "85.52.108.210" ) // External/Public IP

return nil

//----------------------------------------------------------------------------//

Function GetMsgFromServer( oSocket )

   Local cCad     := ""
   Local aEnvio   := {}
   Local cVar
   Local nPosV
   Local cClase   := ""
   Local x

   cCad     := oSocket:GetData()
   if !Empty( At( "|", cCad ) )
      aEnvio   := hb_ATokens( cCad, "|" )
      cClase   := AllTrim( aEnvio[ 1 ] )
      aEnvio   := ADel( aEnvio, 1 )
      aEnvio   := ASize( aEnvio, Len( aEnvio ) - 1 )
      cVar     := aEnvio[ 23 ]
      For x = 1 to Len( aEnvio )
         aEnvio[ x ]  := if( !hb_IsNil( aEnvio[ x ] ), AllTrim( aEnvio[ x ] ), nil )
         aEnvio[ x ]  := if( !hb_IsNil( aEnvio[ x ] ) .and. ( Asc( Left( aEnvio[ x ], 1 ) ) >= 48 .and. ;
                           Asc( Left( aEnvio[ x ], 1 ) ) <= 57 ), Val( aEnvio[ x ] ), aEnvio[ x ] )
         if !hb_IsNil( aEnvio[ x ] ) .and. Valtype( aEnvio[ x ] ) == "C"
            if !( "TBRUSH" $ aEnvio[ x ] ) .and. !( "TMENU" $ aEnvio[ x ] ) .and. ;
               !( "TMENU" $ aEnvio[ x ] )
               if aEnvio[ x ] == ".T."
                  aEnvio[ x ] := .T.
               else
                  if aEnvio[ x ] == ".F."
                     aEnvio[ x ] := .F.
                  endif
               endif
               if Valtype( aEnvio[ x ] ) != "L" .and. Empty( aEnvio[ x ] )
                  aEnvio[ x ] := nil
               endif
            else
               aEnvio[ x ] := nil
            endif
         endif
      Next x
      hb_ExecFromArray( &( cVar ) := &( cClase )(), "New", aEnvio )
      Do Case
         Case cClase == "TWINDOW"
            ACTIVATE WINDOW &cVar
      EndCase
   else
      MsgInfo( cCad ) 
   endif


Return nil

//----------------------------------------------------------------------------//

 
C. Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
Si alguien te dice que algo no se puede hacer, recuerda que esta hablando de sus limitaciones, no de las tuyas.
User avatar
ruben Dario
Posts: 986
Joined: Thu Sep 27, 2007 3:47 pm
Location: Colombia

Re: La magia de los Sockets

Post by ruben Dario »

Excelente Trabajo, cada dia se aprende mas.

Segun el Ejemplo
cuando haces la conexion la clase que usas TSituMySQL() es de Tdolphin

h["oSrv"] := TSituMySQL():New( "localhost", "root", "pampa36", "situ" )

Gracias
Ruben Dario Gonzalez
Cali-Colombia
rubendariogd@hotmail.com - rubendariogd@gmail.com
User avatar
Busmatic_wpb
Posts: 162
Joined: Wed Feb 22, 2017 2:19 am

Re: La magia de los Sockets

Post by Busmatic_wpb »

Estimado Ruben,
Si esta clase me ayudo a desarrollarla Alberio Valencia para facilitarme la coneccion al MYSQL es hererada TDolphy te comento que trabaja de perillas.

_ Chacon.
http://www.Situ.com
Regards.
S.I.T.U.
Sistemas Inteligentes de transporte urbano
http://www.situcr.com
_@Situcr.com
Desarrollos BA4/B4j androide
User avatar
thefull
Posts: 720
Joined: Fri Oct 07, 2005 7:42 am
Location: Barcelona
Contact:

Re: La magia de los Sockets

Post by thefull »

El problema de usar la clase sockets, es que va a través de un contexto de ventana, usando la que viene con FW.
Mi opinión es que montando un simple servidor restful y peticiones http, es más robusto y más simple que usar sockets, y una
razón sencilla es el uso de threads y lo puedes montar como un servicio, y ya lo tienes todo completito.

Ala, ya tienes tema para investigar ;-)
Saludos
Rafa Carmona ( rafa.thefullARROBAgmail.com___quitalineas__)
Post Reply