coronaSDK와 Javascript 연동,

Interface Javascript On CoronaSDK

 

 

Corona SDK: How to communicate between lua and javascript

 

 

This tutorial is meant to provide users who have already some understanding in programming with the knowledge necessary to use the LUA SocketLib and the Coroutines in order to set up a TCP/IP server in a host application.

Introduction

TCP/IP is a large collection of different communication protocols based upon the two original protocols: TCP and IP. TCP is at the fourth level of the OSI model (transport layer) and IP at the third level (network layer). The TCP protocol is used for the data transmission from an application to the network and can handle a byte flow (stream) between a source and an addressee in a total reliable way. A TCP connection is represented by a quintuplet {protocol, IP local_address, local_port, IP remote_address, remote_port} and is unique all over a given network. A connection is totally defined by two half-sockets: the source (client) half socket and the destination (server) half socket [2].

When listening to a port, the TCP server creates a half-socket (server socket). When receiving a connection the server duplicates this half-socket and connects it with the distant half-socket (client socket) in order to build the communication socket that will insure the information data flow. Therefore, at each moment, the server has an available half-socket.

1 - Setting up a TCP/IP server

The usual procedure to create a TCP server can directly be applied with SocketLib functions. This schema is the following one:

  1. Create a server half-socket
  2. Attach the half-socket to a port
  3. Listen on this port

The SocketLib can be used like any other standard library provided with LUA (io, math, string, os, etc.) simply by calling its name, e.g. socket.tcp(). The following code shows how to create the TCP server.

  1. local function createTCPServer( port )  
  2.    local socket = require("socket")  
  3.           
  4.    -- Create Socket  
  5.    local tcpServerSocket , err = socket.tcp()  
  6.    local backlog = 5  
  7.           
  8.    -- Check Socket  
  9.    if tcpServerSocket == nil then   
  10.       return nil , err  
  11.    end  
  12.           
  13.    -- Allow Address Reuse  
  14.    tcpServerSocket:setoption( "reuseaddr" , true )  
  15.           
  16.    -- Bind Socket  
  17.    local res, err = tcpServerSocket:bind( "*" , port )  
  18.    if res == nil then  
  19.       return nil , err  
  20.    end  
  21.           
  22.    -- Check Connection  
  23.    res , err = tcpServerSocket:listen( backlog )  
  24.    if res == nil then   
  25.       return nil , err  
  26.    end  
  27.       
  28.    -- Return Server  
  29.    return tcpServerSocket       
  30. end  


The function socket.tcp() allow us to create a TCP server object. Then one can access the server functions. All the functions used after the creation of the server object are really well known for this kind of job: setoption(), bind() and listen().

Most of the SocketLib functions return one parameter if successful and two parameters if not. If a failure occurs, the first returned value is nil and the second value is the error message.

The function createTCPServer() must be called once during the initialization of the host program. Moreover, if you set it with "localhost", the TCP server will accept only localhost incoming connections (i.e the client is localized on the same computer than the server). So if you wish to be able to connect to your server from a client placed physically in another computer, you have to set host as follow: host = "*"

Creating a TCP server is the easiest part. Now, let us tackle the hardcore one: the acceptation and the management of the in going connections.

2 - Lua: Incoming and outgoing connections management

The guiding principle of managing incoming connections is to set the TCP server in a non-ending loop and to wait for the connections at the beginning of the loop with the server:accept() function. But we immediately see the problem: if we enter a non-ending loop, all the host program will freeze at that point. This is absolutely unacceptable!

The answer to this problem is to transfer this non-ending loop into an execution path separated from the main execution path of the host program. The first function we have to write is a function that parses an URL into a key-value list. Then commands or values sent by the javascript client can be handled in a easier way. Note that we will receive data in a URL fashion.

  1. function getArgs( query )  
  2.    local parsed = {}  
  3.    local pos = 0  
  4.   
  5.    query = string.gsub(query, "&""&")  
  6.    query = string.gsub(query, "<""<")  
  7.    query = string.gsub(query, ">"">")  
  8.   
  9.    local function ginsert(qstr)  
  10.       local first, last = string.find(qstr, "=")  
  11.       if first then  
  12.          local pos = string.sub(qstr, 0, first-1)  
  13.          parsed[pos] = string.sub(qstr, first+1)  
  14.       end  
  15.    end  
  16.   
  17.    while true do  
  18.       local first, last = string.find(query, "&", pos)  
  19.       if first then  
  20.          ginsert(string.sub(query, pos, first-1));  
  21.          pos = last+1  
  22.       else  
  23.          ginsert(string.sub(query, pos));  
  24.          break;  
  25.       end  
  26.    end  
  27.    return parsed  
  28. end  


Due to some bugs related to how Android handles URLs in Honeycomb and ICS, I decided to pass parameters using JASON, eg. we can't simply do

  1. native.showWebPopup("index.html?action=init")  


Hence, we can also send parameters without using a TCP server. Initially, I was using this function together with the next piece of code and a web popup URL listener to handle the communication between lua and javascript. But the approach doesn't work with all devices.

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

  1. -- Write values to be used by webpopup  
  2. function setArgs( args )  
  3.    local path = system.pathForFile( "args.json",   
  4.                               system.DocumentsDirectory  )  
  5.    local file, errStr = io.open( path, "w+b" )  
  6.    if file then  
  7.       local newstr = ""  
  8.       for k,v in pairs(args) do  
  9.          if k ~= nil and v ~= nil then  
  10.             if newstr ~= "" then  
  11.                newstr = newstr .. ", "  
  12.             end  
  13.             local val = ""  
  14.             if type(v) == "boolean" or   
  15.                tonumber(v) ~= nil then  
  16.                   val = tostring(v)   
  17.             else  
  18.                 val = "\"" .. v .. "\""  
  19.             end  
  20.             newstr = newstr .. "\"" .. k .. "\": " .. val   
  21.          end  
  22.       end  
  23.       local content = "{ " .. newstr .. " }"  
  24.       file:write( content )  
  25.       file:close()   
  26.       return true  
  27.    end  
  28. end  


Now we write a function to initialize the TCP server, create a web popup and intercept client requests. The next piece of code illustrates how to do it.

  1. local function doStuff( args )  
  2.   
  3.    -- We set the initial parameters so  
  4.    -- they can immediately be used in our webpage.   
  5.    setArgs( args )   
  6.   
  7.    if runTCPServer ~= nil then  
  8.       Runtime:removeEventListener( "enterFrame",   
  9.                                     runTCPServer )  
  10.    end  
  11.   
  12.    -- We define a function to intercept   
  13.    -- and process client requests.       
  14.    runTCPServer = function()  
  15.       tcpServer:settimeout( 0 )  
  16.       local tcpClient , _ = tcpServer:accept()  
  17.       if tcpClient ~= nil then  
  18.          local tcpClientMessage , _=tcpClient:receive('*l')  
  19.          if tcpClient ~= nil then   
  20.             tcpClient:send(20)                               
  21.             tcpClient:close()  
  22.          end  
  23.          if ( tcpClientMessage ~= nil ) then  
  24.             local myMessage =  tcpClientMessage  
  25.             local event = {}  
  26.             local xArgPos = string.find( myMessage, "?" )  
  27.             if xArgPos then  
  28.                local m = string.sub( myMessage, xArgPos+1 )  
  29.                local newargs = getArgs(m)       
  30.                if newargs.shouldLoad == nil or   
  31.                       newargs.shouldLoad == "false" then  
  32.                   native.cancelWebPopup()  
  33.                else  
  34.                   -- do some stuff ...  
  35.                   newargs.arg = tostring(os.date( "*t" ))  
  36.                   setArgs(newargs)   
  37.                   -- or you can use send    
  38.                   -- tcpClient:send( "some stuff" .. "\n")  
  39.                end               
  40.             end  
  41.          end  
  42.       end  
  43.    end  
  44.           
  45.    if tcpServer == nil then   
  46.       tcpServer, _ = createTCPServer( "8087" )  
  47.    end  
  48.    Runtime:addEventListener( "enterFrame" , runTCPServer )  
  49.   
  50.    -- We set the base url to point to our   
  51.    -- documents directory. To make things   
  52.    -- easier you can pack all your resources   
  53.    -- into a tar file and then uncompress it  
  54.    -- there. A routine to do such this is available.         
  55.    local options = {   
  56.       --hasBackground = false,   
  57.       baseUrl = system.DocumentsDirectory,   
  58.       --urlRequest = function( event ) return true end  
  59.       }  
  60.   
  61.    -- We open the HTML page.  
  62.    native.showWebPopup("index.html", options )  
  63.           
  64. end  

 

3 - Creating a Javascript client

Finally, we have to write a javascript client to communicate with our lua TCP server. Hence, we need two javascript methods: getArgs, to read JSON values from a file called "args.json", and getVariable( name, defaultValue ) to later on access these values.

  1. var urlVars = {}  
  2.   
  3. function getArgs(){  
  4.    try {  
  5.       var xobj = new XMLHttpRequest();  
  6.       xobj.overrideMimeType("application/json");  
  7.       xobj.open('GET'"args.json"false);  
  8.       xobj.send(null);  
  9.       return eval("(" + xobj.responseText + ")");  
  10.    }  
  11.    catch(err){}  
  12.    return null;  
  13. }  
  14.   
  15. function getVariable( name, defaultValue ){  
  16.    try {  
  17.       if (urlVars[name] == nullreturn defaultValue;  
  18.       return urlVars[name];  
  19.    }  
  20.    catch(err){}  
  21.    return defaultValue;  
  22. }  


Then we simply use an AJAX call to request or send data. After sending the data through the TCP server, we call the function update to make values available.

  1. function update( ){  
  2.    urlVars = getArgs();  
  3.    var arg = getVariable( 'arg', 1 );  
  4.    var tag = document.getElementById("method")  
  5.    tag.style.display = 'block';  
  6.    tag.innerHTML = arg;  
  7.    return true  
  8. }  
  9.                                
  10. function send( params ){  
  11.    var xobj = new XMLHttpRequest();  
  12.    var server_ip = "http://127.0.0.1:8087"  
  13.    xobj.open('GET', server_ip + "?" + paramstrue);  
  14.    xobj.onreadystatechange = update( );  
  15.    xobj.send(null);  
  16.    return true  
  17. }  
  18.   
  19. try{  
  20.    window.onload = function () {  
  21.          update();  
  22.    };  
  23. }   
  24. catch(err){}  


One can obtain the full source code here

References

[1] Corona SDK. anscamobile.com. 2012.
[2] Jerome Guinot. The LUA SocketLib and the Coroutines. ozone3d.net, 2006.

 

 

[출처] http://www.think-techie.com/2012/05/corona-sdk-how-to-communicate-between.html

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED