FULL HMG, INTERNET ENABLED APPS: A SIMPLE STORY

I. ONCE UPON A TIME

Some years ago, I’ve started a tiny application for one of my customers. The app, managed some simple transactions and was intended to be used by a single employee on her computer only. So, I’ve used a simple approach: Traditional dbf scheme with exclusive access.

Some time later, the requirement expanded and then, I’ve added a couple of new modules to meet it.

Then… Good News!… another employee could work on the app too, so, more changes were required, then, I’ve put it all in a shared folder, added the required locks and all gone well.

II. THE PRICE OF THE SUCCESS

The app requirements continued growing and growing and a new problem arises: The app should now manage some sensitive information and (remember) it was living in a shared folder on a LAN, so, I’ve been on a big trouble 🙂

My first solution was to left the things exactly the same, except that I’ve started to encrypt the data. Then… I’ve been convinced that I’ve solved my problem with relative small effort… but not.

III. SUPER EASY… OF COURSE!

There is a lot of things that appears to be ‘easy’ and ‘simple’ for the customers… so… one nice day I’ve received the bad news:

“Hey… we need now that the app can be used from two offices outside the city, sharing the same data with us (of course). We have Internet connections everywhere… so… no problem right?”

My answer was “Yes… No problem… let me think on the best implementation…”

IV. THE REMEDY IS WORSE THAN THE DISEASE?

My first thinking was remote desktop, but, to make it work I should have installed a Windows server with a terminal server… but it appeared to me, to be too expensive,too complicated and (most important) a remote desktop is not as good as the real thing (the app running directly on remote users computers).

My second thinking was to create VPN connections with remote clients, so my beloved ‘shared folder’ scheme could survive. This idea lasted very few in my head: It could be very slow and I would have had to deal with the ‘remote’ IT managers, potentially ‘unfriendly’ to let me to mess with their networks 🙂

So, MySql “popped” on my mind and it appeared as a big idea (at least, better than the others)

Then, I’ve finally decided to start the migration towards MySql.

V. YES!

Yes indeed: The remedy was worse than the disease, but not for technical reasons, but, personal ones.

I’ve successfully ported one module of the app to MySql, using SQLMIX RDD.

It worked perfect (technically speaking, at least) but something bothered me…

In fact… two things…

  • I love the standalone/portable EXEs: it is one of the sexiest features on Harbour, but MySql requires a dll.
  • SQL itself: SQL is great… I know… You can do everything with it. The problem is that I don’t feel comfortable with it. My brain, my heart and the rest of my body started to tell me: ‘Hey… SQL is not as easy, intuitive and enjoyable as xBase is… please… STOP THIS!

Then… I’ve done it… I’ve stopped the migration process and started to think again.

VI. A FUNNY THING HAPPENED IN THE WAY TO… CLIENT/SERVER

And I’ve remembered a new Harbour toy called NETIO.

It, basically, could allow you to use your actual code, designed for local access, on a LAN or even through the Internet with minor changes.

The starting tests were very disappointing, because two reasons: at first, my code was written not for efficiency, but, for reliability, simplicity and easy maintenance. Secondly, the remote clients connections were very slow.

It was a difficult moment for me… I’ve stopped all the work and started to reconsider some of my previous ideas…

VII. RPC? WHAT THE F*** IS THAT?

After some days of lurking around remote database access techniques, I’ve remembered something that I’ve read about many years ago: Remote Procedure Call (RPC).

Lets Wikipedia talk:

“In computer science, a remote procedure call (RPC) is an inter-process communication that allows a computer program to cause a subroutine or procedure to execute in another address space (commonly on another computer on a shared network) without the programmer explicitly coding the details for this remote interaction. That is, the programmer writes essentially the same code whether the subroutine is local to the executing program, or remote.”

The following thing happened, was me trying to figure out, how to do that with NETIO.

VIII. A HAPPY END

I’ve re-started NETIO tests, but this time, I’ve created a server application and moved the data handling routines there. These ‘remote’ routines were then called by the ‘client’ app.

The results were amazing. Inside the LAN, NETIO is considerable faster than classic shared-folder scheme and it solves the security risk that this scheme brings.

What about the Internet?

Nearly as fast as the LAN… yes… believe or not… it works nearly the same!

If you think a little, it is very reasonable, since all the data processing is done in the server, so, all dbfs are local from the server app POV.

The data sent from the client to the server are usually some bytes only, being the only possible problem, a result recordset sent from server to client as a response to a query, but since NETIO compresses the data before sending, that is not a problem either.

IX. ARE YOU STILL READING THIS?

Well… thanks and get ready because now the best part comes…

X. THE SERVER

Our demo server will work on port 50000 (you can choose another), it will allow
RCP execution. The data will be compressed and encrypted.

LOCAL nPort		:= 50000
LOCAL cIfAddr		:= '0.0.0.0'
LOCAL cRootDir		:= '.'
LOCAL lRPC		:= .T.
LOCAL cPasswd		:= 'secret'
LOCAL nCompressionLevel	:= 9
LOCAL nStrategy		:= NIL
LOCAL pSockSrv		:= NIL

	pSockSrv := NETIO_MTSERVER( nPort , cIfAddr , cRootDir , lRPC , cPasswd , nCompressionLevel , nStrategy )
	if empty( pSockSrv )
		MSGSTOP("Can't Start Server!")
		RETURN
	endif


Now… we will add to our server, a function that will receive a query string as a parameter and will return a result recordset.

*----------------------------------------------------------------------------*
FUNCTION Query_001(cQueryString)
*----------------------------------------------------------------------------*
LOCAL aRecordSet := {} , cIndex

	cQueryString := ALLTRIM(UPPER(cQueryString))

	cIndex :=  alltrim( STRTRAN ( STR ( HB_RANDOM() , 20 , 17 ) , '.' , '' )    ) + '.ntx'

	USE TEST SHARED

		INDEX ON LAST TO (cIndex) FOR ALLTRIM(UPPER(LAST)) = cQueryString .AND. ( .NOT. DELETED() )

		GO TOP

		DO WHILE .NOT. EOF()

			AADD( aRecordSet , { STR(RECNO()) , LAST , FIRST , STREET , CITY , STATE , ZIP , DTOC(HIREDATE) , IF(MARRIED,'.T.','.F.') , STR(AGE) , STR(SALARY) } )

			SKIP

		ENDDO

	USE

	DELETE FILE (cIndex)

RETURN aRecordSet

XI. THE CLIENT

Our client app, will connect to our server and show queries based on user imput.

At first we must connect:

LOCAL cNetServer	:= '127.0.0.1'	// Server Address
LOCAL nNetPort		:= 50000	// Server Port
LOCAL cNetPass		:= 'secret'	// Server Password
LOCAL nCompressionLevel := 9		// Data Compression Level

	lConnect := netio_connect( cNetServer , nNetPort ,, cNetPass, nCompressionLevel )
	IF .Not. lConnect
		MSGSTOP("Can't Connect To Server!")
	ELSE
		MSGINFO('Connected!')
	ENDIF

The user search string will be on a texbox (Main.Query_String.Value).

Since we should be prepared for large recordsets, we will use a virtual grid.

The following code will retrieve a recordset as a response to the user query and show in Grid_1:

	
	aRecordset := netio_funcexec( "query_001" , Main.Query_String.Value )

	Main.Grid_1.ItemCount := LEN(aRecordset)

netio_funcexec() is the way to execute a function located on the server (in our case “query_001”).

Main.Query_String.Value is our parameter, containing the user’s search expression.

Is important to note that netio_funcexec ‘wait’ until execution on the server ends.

XII. THE DEMO

To make it easy to test, I’ve included (besides the sources and project files) the executables, son you can test immediately.

If you plan to modify it, you will need (at least) HMG 3.4.1 (with bugfix patch).

To test it, you must start the server: \netio\server\server.exe and then, the client: \netio\client\client.exe

Now you are doing ‘local’ RPC, it works well, but the real advantage of NETIO RPC, comes, when you run the server app on another machine (on your LAN or on a remote server).

Now, we will see how to do this…

XIII. NETIO ON A LAN

You just must choose a computer as your server and assure that it has a static IP (if you don’t know how to do it, please, ask to your network admin). Then you must run the server app on it.

Then, you must change ‘cNetServer’ address on your netio_connect() call to use the LAN server address on your client app (the server app will not require changes)

Now, you are doing NETIO RPC on your LAN. It is faster and safer than traditional file server (shared folder) method… A LOT!

XIV. NETIO ON INTERNET

To make available your NETIO server over the Internet, you must do some things:

  • From the LAN”s router, you must to forward the port used in your app to the server local IP.
  • Get a static public IP from your ISP
  • Change, the ‘cNetServer’ address on your client app, with the static public IP that you’ve got from your ISP.

Now you’ll be able to access your server app, from any place.

alternatively, instead of get a static IP from your ISP, you could use any dynamic IP service.

XV. THE SKY IS THE LIMIT!

Had you heard about Android, mobile devices, etc?

I’m pretty sure that your customers does 🙂

So… sooner or later, you should face it and NETIO is the answer for that too.

HDROIDGUI is a wonderful tool,designed to write Harbour apps for Android. It supports NETIO, and its browse widgets can use an array as data source, so… you can do the math…

Yes… exactly the same server app, could allow Android clients to work along WIndows ones… and… yes again… it is so wonderful as it sounds!

XVI. DOWNLOAD THE DEMO!

That’s all, you only must download netio_demo.7z From Here

XVII. DOWNLOAD HMG

HMG Latest Version: Click Here

XVIII. THAT’S ALL

Enjoy!

Roberto.

You can discuss about this post on the HMG SourceForge forum Here

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

17 Responses to FULL HMG, INTERNET ENABLED APPS: A SIMPLE STORY

  1. Anonymous says:

    Thank you Mr. Roberto
    Download link is dead, please

    Like

  2. hmgthinking says:

    It is working for me (It opens download page in a new tab). Which browser are you using?
    Thanks!

    Like

  3. Downloaded with no problem

    Regards

    Esgici

    Like

  4. hmgthinking says:

    Ok. Thanks for the report!

    Like

  5. Esgici says:

    File name to download is : netio_demo.7z
    Click “Download through your browser” button (with world icon in the left side).

    Like

  6. Pingback: New horizons in the HMG | Viva Clipper !

  7. Anonymous says:

    Thank you for excellent contribution and providing expert guidance

    Like

  8. Anonymous says:

    Thank you for expert guidance and excellent demo

    Like

  9. Jayadev says:

    Thanks Roberto for the explanation, frankly, it is because of you and after gentle prodding by Esgici that I have started looking into NetIo.

    Like

  10. Serge says:

    Hi Roberto,
    Another question: How to change the name of the APK. It now called ‘hdnetio’ but I cannot find where this name is given.
    Thx, Serge

    Like

  11. hmgthinking says:

    I’ve not done yet. AFAIK, The ‘right’ way is to create a new project using the utility that HDROIDGUI provides for that.

    Like

  12. Serge says:

    Thanks, found the stuff I need!
    Serge

    Like

  13. Anonymous says:

    Thanks Mr. Roberto.

    For their dedication and sharing with us.

    Like

  14. Anonymous says:

    Dear Roberto
    Eagerly waiting for updated and more feature version

    Like

  15. hmgthinking says:

    By the moment, I’m planning new post about other topics. Anyway, maybe I’ll return to NETIO in the future.

    Like

  16. Javier says:

    Hi,

    I had previously read (years ago) that we need to add net: to manage dbf tables, in the source code I do not see the use of net: and everything works fine .

    how is this possible?.

    Regards.

    Like

  17. hmgthinking says:

    Harbour compiler, natively handles dbf tables. No other thing is required.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s