A Lua programozási nyelv

További információk



Ahhoz, hogy Luában TCP/IP-t tudjunk használni, először is be kell töltenünk a socket library-t a

require("socket")

direktíva segítségével.

Ezután, mint bármilyen más nyelvben, először egy socketet kell kreálnunk a bind függvény hívásával:

server = assert (socket.bind ("*", port))

Itt, ha a port helyére 0-t írtunk, úgy a rendszer választ számunkra portot. Ebben az esetben az

ip, port = server:getsockname ()

függvény hívásával tudhatjuk meg, hogy az OS mely portot allokálta számunkra.

A settimeout(t) függvénnyel tudjuk megadni, hogy az adott műveleteknél (accept, connect, receive) mennyi legyen a maximális várakozási idő. Itt is a -1 az extremális érték, melynek hatására korlátlan ideig várakozik a program. Az accept függvény várakozik a bejövő kapcsolatokra, és amennyiben/amikor van ilyen, úgy visszatér a kliens objektummal. Ezután a receive függvénnyel tudunk üzenetet fogadni, melynek visszatérési értéke egy triple.

line, err, partial_line = tcp:receive() Sikeres üzenet fogadás esetén a line ~= nil, míg az error == nil. Amennyiben a komunikáció során hiba lépett fel, úgy az az error változó értékében jelenik meg, azonban még ebben az esetben is lehet a partial_line változóban részleges üzenet. A lehetséges error értékek közül megkülönböztetett szerepet foglal el a 'timeout', ezt egyszerűen az

err == 'timeout'

-tal vizsgálhatjuk.

Kliens oldalon a kapcsolat létrejöttéhez a

tcp:connect(host, port)

függvényt szükséges meghívni.

Ezután már csak a kommunikáció végén a kapcsolat lezárása maradt hátra, melyet a close () függvény hívásával tehetünk meg.

Az alábbi példakód szemléltet egy lehetséges lefolyást.

server.lua

require("socket") local message = "Hello Client!" local server = nil local port = 1234 function main () server = assert(socket.bind("*", port)) print("Please connect the client to localhost on port " .. port) server:settimeout(-1) local client = server:accept() print ("A client has connected.") local line, err = client:receive() if not err then print (" in << " .. line) print (" out >> " .. message) client:send(message .. "\n") end client:close() end main ()

client.lua

require("socket") local message = "Hello Server!" local host, port = "127.0.0.1", 1234 function main () local line, err, partial_line local tcp = assert(socket.tcp()) tcp:connect(host, port) print (" out >> " .. message) tcp:send(message .. "\n") line, err, partial_line = tcp:receive() if not err then print(" in << " .. (line or partial_line)) end tcp:close() end main ()

Végül egy bonyolultabb beszélgető program, mely épít a Threading fejezetében bemutatottakra is:

client.lua

require("socket") require("task") local message = "Hello Server!" local host, port = "127.0.0.1", 1234 local tcp = nil local name = nil function initTcpIp() host, port = "127.0.0.1", 1234 tcp = assert(socket.tcp()) tcp:settimeout(0) tcp:connect(host, port); end function initInputHandler () local tsk = task.create ("inputhandler.lua", {task.id()}) if tsk == -1 then io.stdout:write( "-> Can't expand task list.\n" ) elseif tsk == -2 then io.stdout:write( "-> Can't strdup file name.\n" ) elseif tsk == -3 then io.stdout:write( "-> Can't create message queue.\n" ) elseif tsk == -4 then io.stdout:write( "-> Can't create os thread.\n" ) elseif tsk == -11 then io.stdout:write( "-> The library seems corrupt.\n" ) else io.stdout:write( "-> Task ", tsk, " started.\n" ) end end function readInput() local buf, _, _ = task.receive( -0 ) return buf end function main() while name == nil do print ("What is Your name?") name = io.read() end initTcpIp() initInputHandler() -- authenticating tcp:send(name .. '\n') local line, err, partial_line while true do message = readInput() if message ~= nil then print (" me > " .. message) tcp:send(message .. "\n"); end line, err, partial_line = tcp:receive() -- if there is no problem then status should be nill -- status can also be "closed" or "timoout" if not err then print((line or partial_line)) elseif err ~= "timeout" then print ("connection " .. err) break end end tcp:close() end main()

inputhandler.lua

require("task") function startReader (parent) while 1 do message = io.read() task.post(parent, message) end end if arg[1] ~= nil then startReader (arg[1]) end

server.lua

require("socket") -- create a TCP socket and bind it to the local host, at any port -- local server = assert(socket.bind("*", 0)) local message = "usage:\n\t\\s - select a user to chat with\n\t\\l - list of all available user" local server = nil local ip, port = nil, nil local clientsAndCoros = {} local members = {} function handleClient(client) local line, err local partner = nil local partnerSocket = nil local name = nil -- firs message should be the name of the user while true do name, err = client:receive() if name ~= nil then if name == "" then client:send("Your user name can not be empty" .. "\n") clientsAndCoros[client] = nil client:close() return elseif members[name] == nil then members[name] = client print (name .. " has come online") break end end client:send("This username is already in use" .. "\n") clientsAndCoros[client] = nil client:close() return end client:settimeout(0) while 1 do -- receive the line line, err = client:receive() -- if there was no error, send it back to the client if not err then --print (" in << " .. line) if string.sub(line, 1,2) == "\\c" then partner = string.sub(line, 4) if partner == name then client:send("You cannot connect to your self" .. "\n") partner = nil end elseif string.sub(line, 1,2) == "\\l" then for member_name, _ in pairs(members) do if member_name ~= name then client:send(member_name .. "\n") end end else if partner ~= nil and members[partner] ~= nil then members[partner]:send(" " .. name .. " > " .. line .. "\n") --partnerSocket = members[partner] --partnerSocket:send(name .. "> " .. line .. "\n") else client:send("You do not have a partner or your partner has disconnected recently\n" .. message .. "\n") end end elseif err ~= "timeout" then break end coroutine.yield() end print ("connection " .. err) clientsAndCoros[client] = nil client:close() members[name] = nil print (name .. " has gone offline") end function initTcpIp() server = assert(socket.bind("*", 1234)) ip, port = server:getsockname() server:settimeout(0) end function main() initTcpIp() print("Please connect the client to localhost on port " .. port) while 1 do local client = server:accept() if client ~= nil then --print ("A client has connected") local coro = coroutine.create(handleClient) clientsAndCoros[client] = coro end for iClient ,iCoro in pairs (clientsAndCoros) do coroutine.resume(iCoro, iClient) end local nConnection = 0 for iClient ,iCoro in pairs (clientsAndCoros) do nConnection = nConnection + 1 end --print ("nConnection: " .. nConnection) end end main()

Bővebben:

luasocket reference