LuaSocket questions

@JakAttak tried the multiplayer demo on two ipads-works like a dream! Thanks for sharing.

@piinthesky, glad to hear it!

@JackAttak this is an awesome piece of code you’ve made here, just one thing-even when my friend and I are on the same wifi, we still can’t connect via the “search and join” feature. Perhaps there are too many peope on the wifi, as it was school wifi? I figured that the problem was that because the 3rd number in our ips did not match, the code was not able to work correctly. I looked at your code, and I believe it only searches 1-255 in the 4th number, am I correct? Anyways, great code, and I will definitely be using this in future projects.

@TheSolderKing this will probably be because schools block certain traffics and use proxies etc, the problem will probably be the latter one as your ips aren’t ‘almost identical’

@TheSolderKing, yes, 255 is the max I believe. Anyways, the best way to do a find and join would really be to use broadcast packets but that’s a little complex… I’ll certainly look into it when I have some time.

@JakAttak sorry to dig up this old thread again, but in your code if a peer is connecting to a host, why do you use self.client:setsockname instead of self.client:setpeername? Is self.client:setpeername only for host sockets? Thanks for answering, and did you ever find out how to use broadcast packets? I looked but I couldn’t find anything on the topic. Thanks again!

@TheSolderKing, I used setsockname because it worked and it allows the code to be essentially the same for the host and client.

Broadcast packets are (from what I can tell, I’m certainly no expert) pretty much just packets sent to the broadcast address, see here: http://en.wikipedia.org/wiki/Broadcast_address

Broadcast packets would work well within a subnet, but there appears to be some restriction: when i try to send a udp packet to a broadcast addr, i get “permission denied”


--# Main
-- Sock

-- Use this function to perform your initial setup
function setup()   
    local socket = require("socket")
    local s = socket.udp()
    s:setsockname("*",0)
    local ip,port,typ = s:getsockname()
    print(s:sendto("hello","255.255.255.255",port))
    s:settimeout(3)
    print(s:receive())
end

@juce, you need to give it the broadcast permission.

s:setoption('broadcast', true)

@JakAttak, thank you! That works great.

There is probably an easier way, but i was trying to do with a broadcast - determine my own IP on the local network.

Code, if anyone needs it:


--# Main
-- MyIp

function setup()   
    local socket = require("socket")
    local s = socket.udp()
    s:setsockname("*",0)
    s:setoption("broadcast", true)
    local ip,port,typ = s:getsockname()
    local bytes,err = s:sendto("hello","255.255.255.255",port)
    if not err then
        local msg
        s:settimeout(3)
        msg,ip,port = s:receivefrom()
        print(ip)
    else
        print("PROBLEM: " .. err)
    end
end 

thanks you @juce.
what about making a bigger program showing sokets usage?
Like a chat between my 2 ipads?
I am totally noob at sokets.

@Juce, I have code above to find your own ip if that’s what you meant.

@Jmv38, I have a two person painting app I’ll share if you want

Jmv38 +1

I too would like to see a complete example that makes it easy to include in a project - maybe a little library?

@JakAttak sure that would be great if you would share it!
Btw, is it possible to connect 2 ipads not on the same wifi local network?

@Jmv38, From the testing i’ve done, i havent been able to do it, but there might be a way to do it

@JakAttak, i figured that you probably have, since you had shared your Multiplayer library :), but i was just experimenting and wanted to start with something simple.

@Jmv38, yes i am writing a small library and will post here as soon as it’s in a useable shape.

It is possible to connect two ipads on two complety separate networks, but it requires a bit more work. I will include an example of that in my code.

@-) Cant wait to see it…

@Jmv38, here it is:

function setup()
    local connectionMade = function()
        output.clear()
        parameter.clear()
        print("Connected!")
        
        gameSetup()
    end
    
    multihandler = Multiplayer(receiveData, connectionMade)
    
    parameter.action("Host Game", function()
        multihandler:hostGame()
    end)
    
    parameter.action("Find Game", function()
        multihandler:findGame()
    end)
    
    parameter.action("Join Game", function()
        if other_ip then
            multihandler:joinGame(other_ip, other_port)
        else
            parameter.text("other_ip", "")
            parameter.text("other_port", "")
            
            print("Fill in the host's ip and port, then click join game again")
        end
    end)
end

function gameSetup()
    canvas = image(WIDTH, HEIGHT)
    parameter.color("pen_col", color(0, 255, 0))
    parameter.integer("pen_size", 2, 100, 10)
    parameter.action("clear", function()
        clear()
        multihandler:sendData("clear")
    end)
    pen_touch = nil
    last_point = vec2(0, 0)
end

function clear()
    canvas = image(WIDTH, HEIGHT)
end

function receiveData(d)
    if d == "clear" then
        clear()
    else
        local tb = loadstring("return " .. d)()
        drawPoint(tb.point, tb.last_point, tb.drawing_line, tb.pen_size, tb.pen_col)
    end
end

function drawPoint(point, lastPoint, drawingLine, penSize, penCol)
    pushStyle()
    setContext(canvas)    -- Start drawing to screen image
    
    fill(penCol) stroke(penCol)    -- Set draw color to color var
    
    strokeWidth(penSize)
    if drawingLine then
        line(point.x, point.y, lastPoint.x, lastPoint.y)    -- draw a line between the two points
    else
        ellipse(point.x, point.y, penSize)    -- Place a dot there
    end

    setContext()
    popStyle()
end

function draw()
    background(255, 255, 255, 255)

    multihandler:update()
    
    if multihandler.connected then
        sprite(canvas, WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)    -- Draw the image onto the screen
    else
        fill(0)
        text("Waiting for connection...", WIDTH / 2, HEIGHT / 2)
    end
end

function vec2ToStr(vec)
    return "vec2" .. tostring(vec)
end

function colToStr(col)
    return "color(" .. col.r .. ", " ..  col.g .. ", " .. col.b.. ", " .. col.a .. ")"
end

function touched(t)
    if multihandler.connected then
        local p, lp, d, ps, pc = vec2(t.x, t.y), last_point, drawing_line, pen_size, pen_col
        if t.state == BEGAN then
            pen_touch = t.id
        end
        if t.id == pen_touch then
            drawPoint(vec2(t.x, t.y), last_point, drawing_line, pen_size, pen_col)
            drawing_line = true
            last_point = vec2(t.x, t.y)
        end
        if t.state == ENDED then
            drawing_line = false
            pen_touch = nil
        end
        
        multihandler:sendData("{ point = " .. vec2ToStr(p) .. ", last_point = " .. vec2ToStr(lp) .. ", drawing_line = " .. tostring(d) .. ", pen_size = " .. ps .. ", pen_col = " .. colToStr(pc) .. " }")
    end
end

Fairly simple stuff, just needs my Multiplayer class as a dependency

thanks, but how can we get the ip and port of another player?
Could you start a game we could join for instance?

@Jmv38, non-local networking is a little more complicated, but I do hope to add it later (I don’t have access to two iPads right now so I can’t do any more work.)

Right now you can just start and join local games (when you start one, it will print your ip and port for the other player to join to )