Got a LiveCode personal license? Are you a beginner, hobbyist or educator that's new to LiveCode? This forum is the place to go for help getting started. Welcome!
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller
-
ace16vitamine
- Posts: 130
- Joined: Fri Apr 13, 2018 1:53 pm
Post
by ace16vitamine » Fri Jun 22, 2018 5:19 pm
Dear all,
my application is sending informations (e.g. License Check) over a SOCKEZ to my Server.
App -> ask to check license -> Server -> Valid yes/No -> App
I do this simple with
Code: Select all
open socket to "localhost:8080"
write socketfile to socket "localhost:8080"
The Server is receiving the datas with
Code: Select all
accept connections on port 8080 with message "someoneConnected"
on someoneConnected theIP
read from socket theIP until "EOL*" with message "newMessage"
end someoneConnected
This is also working
But how can I write an answer from Server to client?
My first idea was on Server
and on the Client
Code: Select all
read from socket "localhost:8080"...
but it seems that this does not work.
Any other Ideas how to solve this?
Stefan
-
dunbarx
- VIP Livecode Opensource Backer
- Posts: 9647
- Joined: Wed May 06, 2009 2:28 pm
- Location: New York, NY
Post
by dunbarx » Fri Jun 22, 2018 5:33 pm
Hi.
I don't use sockets, but might you need to explicitly open a socket when you write back from the server? In other words, it may not be true that just because you opened a socket between those two systems in one direction, that socket was automatically set up to communicate in the other direction.
Or not.
Craig Newman
-
ace16vitamine
- Posts: 130
- Joined: Fri Apr 13, 2018 1:53 pm
Post
by ace16vitamine » Fri Jun 22, 2018 7:04 pm
but might you need to explicitly open a socket when you write back from the server?
maybe. In the final version the client is behind a NAT Firewall, initial TCP communication is not possible from Server to Client.
I don't use sockets,
Alternatives are welcome.
Stefan
-
FourthWorld
- VIP Livecode Opensource Backer
- Posts: 9823
- Joined: Sat Apr 08, 2006 7:05 am
- Location: Los Angeles
-
Contact:
Post
by FourthWorld » Fri Jun 22, 2018 8:18 pm
Is there a reason why HTTP would not be a good protocol here?
-
ace16vitamine
- Posts: 130
- Joined: Fri Apr 13, 2018 1:53 pm
Post
by ace16vitamine » Fri Jun 22, 2018 11:55 pm
hm, you are right and I can work with proxys. Do you now any example sources with livecode http communication?
-
AxWald
- Posts: 578
- Joined: Thu Mar 06, 2014 2:57 pm
Post
by AxWald » Sat Jun 23, 2018 2:29 pm
Hi,
since there's no full reply yet, and I just found I have one here collecting cobwebs, here we go:
The Server code:
Code: Select all
global gRunning, gPort
on ServerStart
put "8080" into gPort -- or whatever portNum you choose
if not gRunning then
put true into gRunning
accept connections on port gPort with message "ClientConnect"
end if
end ServerStart
on ClientConnect theSock
put "Hello!" into MyMsg
write "CON OK, " & length(MyMsg)& return & MyMsg to socket theSock
read from socket theSock until return with message "MsgReceive"
end ClientConnect
on MsgReceive theSock, theMsg
put item 1 of line 1 of theMsg into MyCmd -- CMD received
put Item 2 of line 1 of theMsg into MyLen -- Length(Payload)
read from socket theSock for MyLen chars -- get the Payload
put it into myPL
-- here we process the client request:
put MSGHandler(MyCmd,myPL) into MyResult -- handle a Cmd
-- //
write MyCmd & " OK," & length(MyResult) & return & MyResult to socket theSock -- and reply
read from socket theSock until return with message "MsgReceive"
end MsgReceive
function MSGHandler theCmd, thePL
switch theCmd
case "ART"
-- an example - we have an article number and the customers price group,
-- and want the currently available amount of the article, and the custom price for our customer
put line 1 of thePL into myArtNum -- the article number
put line 2 of thePL into myPriceGroup -- the price group
put "SELECT `article`.price, `supply`.available " & \
"FROM `article` LEFT JOIN `supply` ON `article`.id = `supply`.article " & \
"WHERE `article`.number = '" & myArtNum & "';" into StrSQL
put getSQL("WEBDB",StrSQL) into myArtData
-- using our "getSQL interface" (it does all the db stuff)
-- we ask our "WebDB" for the base price of the article & its available amount
set itemdel to tab
put item 1 of myArtData into myPrice
put item 2 of myArtData into myAvail
put "SELECT mod FROM `pricegroups` " & \
"WHERE `pricegroups`.id = " & myPriceGroup & ";" into StrSQL
put getSQL("CACHE",StrSQL) into myPMod
-- we check our cache SQLite for the suitable price modificator
put round(myPrice * myPMod,2) into myPrice
return myPrice & return & myAvail -- answer with the desired data
break
case "CUS"
-- ...
break
default
return empty
end switch
end MSGHandler
and Client code:
Code: Select all
global gSocket, gPort
on StartCon theServer
if gPort is empty then put "8080" into gPort -- or whatever portNum you choose
if gSocket is empty then
open socket to theServer & ":" & gPort with message "ServerConnect"
end if
put "Connected to server " & theServer & return after field "logFld"
end StartCon
on ServerConnect theSocket
put theSocket into gSocket
read from socket gSocket with message "MsgReceive"
put "Server accepted me!" & return after field "logFld"
end ServerConnect
on MsgReceive theSocket, theMsg
put "<- : " & theMsg & return & "----------" & return after field "logFld"
read from socket theSocket with message "MsgReceive"
end MsgReceive
on MsgSend
-- a button will call this
put fld "CmdToSend" into myCmd -- A command, so the server knows what to do with the msg
put fld "DataToSend" into myPayLoad -- additional data that the server requires to do it's work
if gSocket is not empty then
put myCmd & "," & length(myPayLoad) & return & myPayLoad into myData
write MyData to socket gSocket
end if
put "-> : " & myData & return after field "logFld"
end MsgSend
This needs some additional information:
- To make communication possible a common protocol (= language) is desirable. Here we use a very simple but versatile one:
Code: Select all
[COMMAND],len(PAYLOAD) {CR}
[PAYLOAD]
Using an example from the server scripts MSGHandler function, it could look like this:
--> Client sends: -->
Translate: "I have ARTiclenumber 000521 and a customer with a pricegroup of 89 - how much this customer must pay, and how much of this article is available?"
<-- Server replies: <--
Translate: "Your request has been considered OK - the price is 125.10 and we have 1305 of the article left."
So "COMMAND" designates what to do with the data, len(PAYLOAD) is used to determine the boundaries of the data for easy reading, and "PAYLOAD" is the data itself.
.
- The Server code contains a function "MSGHandler" with an example command. I hope it's comprehensible what it does :)
Besides, I'd always use a local SQLite db (maybe replicated) as cache - it's this much faster! Any calls to remote dbs (as in the example) will be a serious bottle neck to the immense possible speed of the socket server.
.
- The code is based on an actual implementation of a socket server that runs 24/7/365 for quite some years now. It connects a web shop to an in-house Server (Single Xeon 3GHz) and handles authorizations, customer specific "special offers" & prices and the orders - the web shop itself has no customer data, no prices, nothing sensible in its db. All that is provided by the socket server.
.
- Disclaimer:
The code should run, but I haven't tested it. It may contain typos, misspelled variable names, unavoidable nonsense and such. And I have removed all & any error checking, to make more understandable how it works.
Have fun!
All code published by me here was created with Community Editions of LC (thus is GPLv3).
If you use it in closed source projects, or for the Apple AppStore, or with XCode
you'll violate some license terms - read your relevant EULAs & Licenses!