2

my question is about lua sockets, say I have a chat and I want to make a bot for that chat. But the chat has multiple rooms all on defferent servers that are calculated by a function called getServer the connect function would look like this

function connect(room)
   con = socket.tcp()
   con:connect(getServer(room), port)
   con:settimeout(0)
   con:setoption('keepalive', true)
   con:send('auth' .. room)

and the function to loop it would be

function main()
   while true do
     rect, r, st = socket.select({con}, nil, 0.2)
     if (rect[con] ~= nil) then
        resp, err, part = con:receive("*l")
        if not( resp == nil) then
            self.events(resp)
 end
    end
       end
          end

now when all that runs it only receives data from the first room and I dunno how to fix that

user3103366
  • 65
  • 1
  • 9
  • Show the code where you call connect() for each rooms, and the main, don't show pieces. And fix the bad indentation. – Oliver Mar 24 '14 at 20:34
  • I'll link it to a github repo because the file is to big ;( [link Github](https://github.com/ericraio/ch.lua/blob/master/ch.lua)[link] just add the socket.select() and thats pretty much what i got – user3103366 Mar 24 '14 at 20:38
  • This is not what I meant. Show the code that calls `connect(room)` and the code that calls `main()`. The link you attached contains neither of those. – Oliver Mar 24 '14 at 20:46
  • I'm sorry, the `main()` function is the `ch_handler` function and the connect is called inside `ch_init` and the `ch_init` function is called in example.lua here [link example.lua](https://github.com/ericraio/ch.lua/blob/master/example.lua) – user3103366 Mar 24 '14 at 20:56
  • 2
    You need to create a [SSSCE](http://www.sscce.org/). Too much code. Perhaps the con, which is a global set in ch_connect and then used in ch_handler, but every connection will overwrite the reference with latest connection? – Oliver Mar 24 '14 at 21:32
  • then if it overwrites how do I fix it, if this was python i'd just point the connection to a dict of the room name and then make a getCons function that returns the key and value lists then i would create a readers and writers list pass that onto the select then iterate through the read list – user3103366 Mar 25 '14 at 20:53

1 Answers1

1

Try creating an array of connections. A map of room to connections might also be useful. Example:

local connections = {}
local roomConnMap = {}

function connect(room)
   local con = socket.tcp()
   con:connect(getServer(room), port)
   con:settimeout(0)
   con:setoption('keepalive', true)
   con:send('auth' .. room)

   table.insert(connections, con)
   roomConnMap[room] = con
end

function main()
   while true do
     local rect, r, st = socket.select(connections, nil, 0.2)
     for i, con in ipairs(rect) do 
        resp, err, part = con:receive("*l")
        if resp ~= nil then
            self.events(resp)
        end
     end
   end
end

Note that rect is an array of items found connections for which there is data to be read. So in the for i,con loop the con is the connection object, do not use connections[con] (this doesn't make sense because connections is an array, not a map).

Oliver
  • 27,510
  • 9
  • 72
  • 103
  • I've tried this, first it says attempt to call a table value so I did `for con in ipairs(rect) do` and it never actually connects to the room – user3103366 Mar 25 '14 at 23:30
  • not exactly when I run with your code it connects to the room but doesn't receive data then I did, `for con in ipairs(rect) do resp, err, part = connection[con]:receive('*l')` because from what I understand. `socket.select()` Uses an array and that array holds every connection, selects job is to wait to receive data then outputs that connection as a number so for example connection holds two connections r1, r2. When r1 is receiving data the con value is 1 and when r2 receives data the con value is 2 right? But when it does get data it outputs an error. – user3103366 Mar 26 '14 at 20:44
  • that says, `attempt to index field '?' (a nil value)` and that error is coming from the `receive()` – user3103366 Mar 26 '14 at 20:49
  • 1
    @user3103366 That's because I had a couple bugs in the code I put. See if this is better. The code in your comment is missing a `i` which I put in my updated answer, and explain why not to use `connection[con]`. Note I used `connections` not `connection` since it is an array. Hope it works now. – Oliver Mar 26 '14 at 21:43
  • thanks so much, it works now. The funny thing is I tried the for loop that way once before but I forgot to use ipairs instead of pairs this issue is resolved – user3103366 Mar 26 '14 at 22:44
  • Awesome' good to know. Don't forget to upvote any answers you find useful (for all questions you read, not just your own questions). – Oliver Mar 27 '14 at 00:36