Hello all,
Not sure much of us would know about this topic as it has yet to be implemented in to Codea(unless you are a beta tester, and even then it’s not documented), but I have been taking a look at the LuaSocket docs and have a few questions I was hoping I could get answered:
Will the Codea implementation of LuaSocket be changed at all from the normal library? Just wondering, and I assume not.
In most multiplayer games, you can scan for local games. Is there a way to do this, to check for IP’s on the local network hosting games and then connect to the sockets from there with any of the LuaSocket libraries?
Can you send anything other than strings over the sockets? I don’t really care, but if it is just strings then I see a lot of loadstring()() in my future.
Will TCP be the only implementation of LuaSocket, or will there be any others such as FTP, etc?
Thanks for taking the time to read my stupid questions if anyone knows, and answering this brings me one step closer to building a simple multiplayer library for you all! Thanks!
@Ignatz I think @toffer does, he posted this code that works:
function setup()
socket=require("socket") --EDIT added by ignatz
server = socket.tcp()
-- Replace with your local IPad ip
server:bind("ip goes here, example: 123.456.7.89",52096)
server:listen()
server:settimeout(0.0)
local ip,port = server:getsockname()
print("please telnet to", ip, "on port", port)
client = nil
buf = {}
end
local _twu = tween.update
tween.update = function(...)
if not client then
client = server:accept()
if client then
client:settimeout(0.0)
local ip,po = client:getsockname()
client:send("Welcome to the REPL mr(s) "..ip.." "..po.."\
")
client:send("Type bye to quit\
")
end
end
if client then
local lin, err = client:receive()
if not err then
if lin == "bye" then
client:close()
client = nil
else
table.insert(buf,lin)
local f,e = load(table.concat(buf,"\
"))
if not e then
f()
client:send("> eval\
")
buf = {}
end
end
end
end
_twu(...)
end
The ip address referred to in the code above is your internal network ip. You get this from Settings, tap your (ticked) Wifi provider and you should see an ip address.
toffer has used a clever hack to keep listening for socket messages. He replaces the normal tween update function (which runs each time a frame is drawn) with the function above, so it checks for socket messages instead. He has, however, stored the name of the original tween update function in _twu, and runs this at the end of the function above, so that the tweens do get updated. So he has basically just added some code into the tween update function.
This means that Codea will run normally while the socket is listening.
EDIT - it worked fine to start with, now Codea knows when I send messages from my PC, but doesn’t recognise “bye” and is unable to print what I type. Hmmm…
:-?
For example, if I wanted to send data between two iPads I believe it would be something like this:
function setup()
socket = require("socket")
local myip, myport = getLocalIP(), 5400
print("Connect to " .. myip .. ":" .. myport)
server = socket.udp()
server:setsockname(myip, myport)
server:settimeout(0)
client = socket.udp()
client:setpeername(myip, myport)
client:settimeout(0)
parameter.text("msg_to_send", "")
parameter.action("send message", sendMessage)
end
function getLocalIP()
local randomIP = "192.167.188.122"
local randomPort = "3102"
local randomSocket = socket.udp()
randomSocket:setpeername(randomIP,randomPort)
local localIP, somePort = randomSocket:getsockname()
randomSocket:close()
randomSocket = nil
return localIP
end
function sendMessage()
client:send(msg_to_send)
print("Client sent to server: '" .. msg_to_send .. "' at", os.date("%x, %X", os.time()))
end
function draw()
background(255, 255, 255, 255)
local data, msg_or_ip, port_or_nil = server:receivefrom()
if data then
print("Server received from client: '" .. data .. "' at", os.date("%x, %X", os.time()))
end
end
Though obviously the client code would run on one and the server code on the other.
EDIT: updated with method to get local ip (so the server iPad could tell you it’s ip, which you could then tell the client iPad to connect to)
@JakAttak Is the code working correctly. If I put in an ip of 0.0.0.0 , the ip stays at 0’s, but it still says the message was sent and received. I don’t know anything about sockets, so I can’t say what’s happening.
@dave1707, I believe it will work as long as the ip given to the client and server is the same. Of course, the true test will be running this on two iPads, which I will try once 2.3 comes out.
Thanks everyone for your help and example code! You answered most of my questions, but still, is there any way I can make a game where both players do not need to know the other’s ip, ie scanning for nearby games? Thanks!
@TheSolderKing, well, the programs will still heed to know each other IPs, in order to communicate efficiently. Several ways that can be done.
One approach could be as simple as periodically broadcasting your ip via a specially addressed (255.255.255.255) udp packet, which gets delivered to all devices on your local network. The packet can contain a simple message like: “my ip is 192.168.1.5” or whatever it is. Another client does the same, and this way they can discover each other.
Another approach could be writing a discovery service, which could be running on your desktop computer, and then each client will be able to register with it, and also ask for all the others who had registered with it too. (that could be a simple HTTP service, you don’t necessarily need to use raw sockets)
@TheSolderKing, @juce - for home networks, local ip addresses are usually sequential and only the last digit changes, perhaps making it easy to scan for a player who sets up as the server.
@Ignatz, that’s true. Just scanning the IPs sequentially would sort of work too, although then you have to guess what valid range is and such. I guess my main point (which i failed to mention ) was that the whole process consists of two steps:
Discover the peer to play with
Use discovered IP addr of the peer to communicate directly
I haven’t tried the latest code above, but using toffers’ code, I was able to send messages but not read them at the other end, eg pritning them showed nothing, and “bye” wasn’t recognised