Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Mobile server — Gideros Forum

Mobile server

ar2rsawseenar2rsawseen Maintainer
edited June 2012 in General questions
Hello all,
I'm quite new to networking and wanted to explore the dark waters with Gideros. So I wanted to create simple server app, to which other could connect. Probably similar to Gideros Player.

So I tried this piece of code
-- load namespace
local socket = require("socket")
local ip, t = socket.dns.toip("localhost")
-- create a TCP socket and bind it to the local host, at any port
local server = assert(socket.bind(ip, 53883))
-- find out which port the OS chose for us
local ip, port = server:getsockname()
-- print a message informing what's up
print("Please telnet to "..ip.." on port " .. port)
print("After connecting, you have 10s to enter a line to be echoed")
-- loop forever waiting for clients
while 1 do
  -- wait for a connection from any client
  local client = server:accept()
  -- make sure we don't block waiting for this client's line
  client:settimeout(10)
  -- receive the line
  local line, err = client:receive()
  -- if there was no error, send it back to the client
  if not err then client:send(line .. "\n") end
  -- done with client, close the object
  client:close()
end
Which allows me to connect to localhost through putty on same port, but then after some time it says server has stopped unexpectedly. And when I check Gideros player it's simply hangs (Not responding).

I'm probably doing something completely wrong using while loop. So how does one can create a server app?

Likes: techdojo

Tagged:
+1 -1 (+1 / -0 )Share on Facebook
«1

Comments

  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    If you'll wonder about the purpose, then I want to create a real time game, that can be simply played between two phones in LAN, without any third parity server.

    Is it even possible?
    That app should both listen and send data
  • ar2rsawseenar2rsawseen Maintainer
    Ok, it's probably due to my slow machine, tried on PC and it works ok.

    But still interested from point of efficiency, is it ok for app to be a server?
  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    This is how far I got and it works great.
    -- load namespace
    local socket = require("socket")
    local ip, t = socket.dns.toip("localhost")
    -- create a TCP socket and bind it to the local host, at any port
    local server = assert(socket.bind(ip, 53882))
    -- find out which port the OS chose for us
    local ip, port = server:getsockname()
    -- print a message informing what's up
    print("Please telnet to "..ip.." on port " .. port)
    print("After connecting, you have 10s to enter a line to be echoed")
    -- loop forever waiting for clients
    local clients = {}
    local maxClients = 2
    local writeClient = {}
     
    while 1 do
    	local ready, none, erra = socket.select(clients, writeClient, 10)
    	if err == nil then
    		for i = 1, maxClients do
    			local client = clients[i]
    			if client == nil then
    				-- wait for a connection from any client
    				client = server:accept()
    				-- make sure we don't block waiting for this client's line
    				server:settimeout(1)
    				if client then
    					clients[i] = client
    				end
    			end
    		end
    		for i = 1, #ready do
    			local client = ready[i]
    			-- receive the line
    			local line, err = client:receive()
    			-- if there was no error, send it back to the client
    			if not err then 
    				if line == "exit" then
    					-- done with client, close the object
    					client:close()
    					clients[i] = nil
    				elseif line == "whoami" then
    					client:send(client:getpeername().."\r\n")
    				elseif line == "howdidigethere" then
    					client:send(client:getsockname().."\r\n")
    				elseif line == "whattimeisit" then
    					client:send(socket.gettime().."\r\n")
    				else
    					client:send("Unknown command: "..line.." \r\n")
    				end
    			end
    		end
    	end
    end
    Will keep updating snippet and probably someday create a tutorial :)

    Likes: atilim, phongtt

    +1 -1 (+2 / -0 )Share on Facebook
  • atilimatilim Maintainer
    edited June 2012
    <:-P I'll learn a lot from your tutorial.
  • ar2rsawseenar2rsawseen Maintainer
    Ok created some sort of device discovery using udp broadcasting (255.255.255.255), which works great between two pc's in Gideros player.
    But once I try it on Android's Gideros player, it does not receive any broadcasted packages. I can send messages directly to Android using it's IP, but not broadcast.

    Another interesting thing, that to get PC's IP address I simply use
    socket.dns.toip(socket.dns.gethostname())
    But on Android it returns 127.0.0.1, so I have to manually set up current Android's IP to bind socket to, to make it work.

    Is there any other way to get current device's IP address?

    Did a lot of reading, and many says that both problems are because of multiple interfaces, and that currently used interface to connect to LAN is not default.

    So broadcasting goes to default interface and IP address returned for default interface.

    Still don't know if it's true, but is there any option to change interface on device (I always thought that my Android has only WiFi) and is there a way to get list of all device interfaces?

    And another question if someone might know, is there a way to identify clients, right now I'm implementing my own protocol, but maybe there is easier way? :)
  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    Ok resolved detecting IP address problem, not an elegant solution, but it works:
    http://stackoverflow.com/questions/7046291/get-ip-address-in-lua
    local function getIP()
    	local s = socket.udp()
    	s:setpeername("74.125.115.104",80)
    	local ip, _ = s:getsockname()
    	return ip
    end
  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    Resolved device discovery using multicast

    Although, I don't know why, my PC does not want to bind socket to multicast address, simply says: Cannot assign requested address

    But at least between devices it works :)

    And also found out better docs for Lua Sockets
    https://github.com/sam-github/luasocket/tree/unstable/doc

    A lot of undocumented features are there, for example, multicast :D

    Likes: atilim

    +1 -1 (+1 / -0 )Share on Facebook
  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    Current result:


    It now seems obvious, that another thread is needed.

    Right now I'm using Timer, which at least does not block UI completely (like loop), but still it's too slow

    Any hacks for separate thread? :D

    Likes: gorkem

    +1 -1 (+1 / -0 )Share on Facebook
  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    It must be magic, but every time I write here, I get back to the project and resolve the question I posted here. That's why I'm kind of talking to myself here, and will continue to do it :D

    But well, it seems that by setting timeout to 0, then sockets are completely not blocking UI. :D

    Result is much better:

    Likes: atilim, MoKaLux

    +1 -1 (+2 / -0 )Share on Facebook
  • atilimatilim Maintainer
    looks great! I'm enjoying this thread a lot. :)

  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    No, haven't tried it. Right now I'm ok on my own :D

    Well actually, I came to an idea to develop a little LuaSocket framework for Gideros, let's call it "Unite" for now.
    It would allow to create servers on mobile phone, discover other phones, allow other phones to join the server and then call Gideros functions on other devices through network.

    The video that was posted before will be an example app for this framework. First version will be far from production version, and I'll need you guys to test it too, because as I said I have little knowledge of networking, all I did was through experiments, what works and what is not. So I'm more than sure I didn't cover all scenarios.

    Hopefully I'll be done by the weekend and then post you guys to try it out.

    Likes: atilim, Mells, gorkem

    +1 -1 (+3 / -0 )Share on Facebook
  • ar2rsawseenar2rsawseen Maintainer
    But all in all, yeah a lot of new stuff, for example, you can't send tcp message, without new line symbol in the end of message. (Took me couple of hours to figure out)

    and a lot of this kind of stuff

    Likes: atilim

    +1 -1 (+1 / -0 )Share on Facebook
  • @ar2rsawseen I totally don't understand how you do this but I can see how this would be useful., nice work.
    twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
  • ar2rsawseenar2rsawseen Maintainer
    Well I'll also try to post a more detail tutorial on how things work.
    Examples for both tcp (server/client) udp (server/client), udp(broadcast/multicast)
    That should clear up some things
    ;)

    I probably haven't mentioned, but that's actually my homework for Networking course in University. Build your own communication protocol on top of tcp or udp and create an application using it. (Bonus points if it's a mobile application)

    So this was a no brainer, where and how I should create it :D

    Likes: gorkem, MoKaLux

    +1 -1 (+2 / -0 )Share on Facebook
  • MichalMichal Member
    But all in all, yeah a lot of new stuff, for example, you can't send tcp message, without new line symbol in the end of message. (Took me couple of hours to figure out)
    I think you are wrong here. Sending out is not buffered by LuaSocket, you can verify this with some network sniffer (like wireshark).
    But if you are reading data with receive('*l'), then the client waits for the new line. You should then use receive('*a') or receive(8192) (or any other burref size).

    BTW, your example would work faster if you used UDP instead of TCP. You can check this out: https://love2d.org/forums/viewtopic.php?f=3&t=3289&start=10#p33373
  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    Finally someone who understands something. :D
    Thank you.

    Well I agree UDP works faster, right now I'm struggling with optimizing TCP, to catch up with UDP speed. I just can't believe that difference is so huge, I must be simply doing something wrong with TCP.

    But as I understood, then you can't rely on UDP to deliver the packages, if for example one of the devices looses the connection, and then establishes it again. TCP however would still deliver them. Am I right?

    Meaning how much can I rely on UDP?
  • MichalMichal Member
    If you have followed the link I gave you, you should also read some previous messages on that forum. In short: for 99,9% you can rely on UDP, and on top of the UDP you can send/receive PING packets to discover closed connections. Download the archive MultiCircles.zip and read MultiCircles/UDPIPE.txt
  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    I completely agree that if everyone is connected udp is as almost as reliable as tcp, but my question was about situation, when device looses connection and reconnects.

    Well, although I managed to get almost as same speed as with udp (by changing, reading/listening order), I guess, I could leave it as an option, what to use udp of tcp :)
  • MichalMichal Member
    FYI: UDP is connectionless protocol: you send out a packet, and it either gets delivered or not (and that is why it is faster than TCP). With TCP, every packet delivered has to be ACKnowledged, which causes delays.
    Other use of UDP is hole punching: connecting two devices which are behind a NAT. TCP would not work, UDP usually would work.
  • ar2rsawseenar2rsawseen Maintainer
    So I added a project for anyone who wants to test. Consider it version 0.1.
    You need to start project simultaneously on multiple devices (or PC and device, also with some PC's, depending on configuration, firewall, etc discovering might not work).

    Then select one of them as server, and on other devices select option to join.

    Then there will be list of servers, to which you can join, then on server device you need to accept this device. Then on clients device a button draw will appear, when you accept all clients you want, you may start drawing together :)

    You can check the code and comments right now, if you want to know more.
    File Unite.lua contains the Server and Client classes,
    new_server.lua is the scene for servers
    join_server.lua is the scene for clients
    and in draw.lua is the scene of drawing, where it does not matter anymore whether you are server or client, you simply call functions on all other devices and that's it.

    So tell me what you think and if it even works on your devices in your LAN.

    zip
    zip
    DrawTogether.zip
    311K
  • Amazing - didn't work from PC to device (at work - not surprising), however @Scouser and I both linked our ZTE-Blades and it just worked!!!

    I was going to try linking my iPod to my Blade but the player on my iPod is out of date and doesn't have the socket module in it :(
    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • yvz5yvz5 Member
    great job!

    i was looking to find a way to stream pc's sound output to my mobile. for example, i wanna watch a movie but its quite late at home and i wanna lay on my bed but i dont have a headset with a long cable. so a server app runs on pc and handles the sound output and sends it throughout tcp or udp protocol to the client(my mobile). but it was soooooo dificult to do it on my symbian phone.
  • Talk about an over engineered solution :)
    Interesting idea (and potentially useful for other apps), but wouldn't getting some kind of audio extension cable be easier? :)
    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • MichalMichal Member
    great job!

    i was looking to find a way to stream pc's sound output to my mobile. for example, i wanna watch a movie but its quite late at home and i wanna lay on my bed but i dont have a headset with a long cable. so a server app runs on pc and handles the sound output and sends it throughout tcp or udp protocol to the client(my mobile). but it was soooooo dificult to do it on my symbian phone.
    You should look for UPNP server (or a stand-alone external disk with such a server) and a UPNP player for your phone. Works for me.
  • yvz5yvz5 Member
    Talk about an over engineered solution :)
    Interesting idea (and potentially useful for other apps), but wouldn't getting some kind of audio extension cable be easier? :)
    it would be easier, but where is the innovation part ? :P

    You should look for UPNP server (or a stand-alone external disk with such a server) and a UPNP player for your phone. Works for me.
    i ll give it a try



  • it would be easier, but where is the innovation part ? :P
    Fair point - can't argue with that :)

    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • I did the same thing back in June. I made an AI server that acts as the 2nd player in my game. The game was created in Corona (sorry. I want to port it to Gideros as I'm sick of Corona) but the server part is pure Lua with LuaSocket. The server will handle multiple clients playing completely separate games.

    Likes: MoKaLux

    Dan Huffman, Creator of The Octagon Theory
    http://TheOctagonTheory.com
    +1 -1 (+1 / -0 )Share on Facebook
  • I forgot to mention that the server is not a compiled standalone app. It is just a Lua script that runs in the iLuaBox app.
    Dan Huffman, Creator of The Octagon Theory
    http://TheOctagonTheory.com
  • Wow, that is awesome. I imagine how well it could be used for application testing.
    Is there any intention of sharing the code on specific license?
Sign In or Register to comment.