This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Saugrim's profile picture

[LUA][Question] Server Multitasking

Started by Saugrim, 17 October 2012 - 10:18 PM
Saugrim #1
Posted 18 October 2012 - 12:18 AM
I've been working on Internet in Tekkit for the last few days and I've come across a little snag.. Anyways, I've got a server that is beginning to look more and more upon the Internet for their needs, and this has led to many issues with the current server since it waits a maximum of 60 seconds for every request before moving on.. This can send people into loops and what not, and I was wondering if there was a way to make it so the server could either run multiple people at the same time, or send a message when it is busy..

I use functions to handle everything, so I have been thinking of using the parralel function, but I'm not sure if that would really work or not.. Anyways, I'll post the code below to show what the current issue is, and see if maybe anyone can give me an idea or fix.


function Download()
print("Processing request from "..(ID).." ")
rednet.send(ID, "DownloadProt")
ID, message, distance = rednet.receive(30)
x = message
p = ID
if x == nil then
shell.run("server")
elseif x ~= nil then
checkf = fs.exists("Files/"..(x).."")
if checkf ~= true then
rednet.send(p, "exist")
r()
elseif checkf == true then
h = fs.open("Files/"..(x).."", "r")
content = h.readAll()
rednet.send(p, ""..(content).."")
shell.run("server")
else
shell.run("server")

end
end
end



Thanks for any assistance,
Saugrim
Lyqyd #2
Posted 18 October 2012 - 01:06 AM
Please post the whole code.
Saugrim #3
Posted 18 October 2012 - 03:13 AM
The entire code is over 1,500 lines of code.. For both the server, and the client.
So, I don't think you want to read through the entire thing.

All I need to know is if it's possible, and I need to see examples of how it could be done, I can figure out most of the other stuff for myself.

However, I suppose this part of the code is important as well since it shows how the server pulls up events, and handles them.


ID, message = rednet.receive()

if message == "Upload" then
Upload()

elseif message == "Override" then
override()

elseif message == "Download" then
Download()

else
shell.run("server")

This is the code for the file receiving server which is the one that works on a more defined principle of sending messages back, and forth to request new information.

I had an issue when I was hosting the FTP functions from the main Internet server, and so I incorporated a backup function into Blocko (The Web Browser) which then allowed for it to ping, and if no response was received it would automatically try the secondary server, which could handle the same functions.
However, with a FTP server that can be a serious flaw since it can cause issues with file sync, and of course I don't want like 50 backup servers hence why I wanted to see if there was a way for the server to be responding to an Upload request for example while waiting for other requests, or while sending messages back for the pinging saying that it is currently dealing with operations.
Lyqyd #4
Posted 18 October 2012 - 03:47 AM
Yes, there is. First things first, don't run the program again to continue it. You'll just overflow the stack that way. while loops are your friend. Second, you'd be better off keeping track of the state of each request by computer ID, then responding appropriately. You'll probably want to keep a table of computer IDs as the keys and the current state as the values. So, if a computer asks to download a file, it'd be stateTable[id] = "download". Then you'd check the current state whenever you got a packet and act accordingly. With that method, you can field as many requests as possible without needing time limits or such. And we don't mind large code, just use the spoiler tags around the code tags so that it won't take up huge amounts of space. You may wish to look up tutorials on using loops and on using tables in the Tutorials section of the forums if you're unfamiliar with either.
Saugrim #5
Posted 18 October 2012 - 04:16 AM
Alright well this is the entire code for the smaller server..
The larger server doesn't require any time since the file is sent instantly with no delay.

It is a more basic server, since I did this all in a day.. I was sort of planning on updating it all to a more suitable running environment as the need got increased, and well I decided that I should probably get started.

Spoiler

rednet.open("top")
term.clear()
term.setCursorPos(1,1)
y = "Active"
print("Server status: "..(y).." ")

-- Functions
function r()
h = fs.open("log", "a")
h.writeLine("Computer #"..ID.." Requested: "..(message).."n")
h.close()
shell.run("server")
end


function log()
l = fs.open("Files/filelog", "a")
l.writeLine("n"..(x).."")
l.close()
shell.run("server")

end

-- Receiving
function Upload()
print("Processing request from "..(ID).." ")
rednet.send(ID, "UploadProt")

ID, message, distance = rednet.receive(30)
x = message
p = ID
if x == nil then
shell.run("server")
elseif x ~= nil then
checkf = fs.exists("Files/"..(x).."")
if checkf == true then
rednet.send(p, "exist")
r()
elseif checkf ~= true then
rednet.send(p, "Okay")
ID, lawl = rednet.receive(30)
if lawl == nil then
shell.run("server")
elseif lawl ~= nil then
n = fs.open("Files/"..(x).."", "w")
n.writeLine(""..(lawl).."")
n.close()
rednet.send(p, "Success")
log()
else
print("This is active!")
sleep(10)
shell.run("server")
end
end
end
end

-- Download

function Download()
print("Processing request from "..(ID).." ")
rednet.send(ID, "DownloadProt")
ID, message, distance = rednet.receive(30)
x = message
p = ID
if x == nil then
shell.run("server")
elseif x ~= nil then
checkf = fs.exists("Files/"..(x).."")
if checkf ~= true then
rednet.send(p, "exist")
r()
elseif checkf == true then
h = fs.open("Files/"..(x).."", "r")
content = h.readAll()
rednet.send(p, ""..(content).."")
shell.run("server")
else
shell.run("server")

end
end
end

-- End of Download

-- Override

function override()
rednet.send(ID, "OP")
ID, message = rednet.receive(10)
if message == "73185DFSAFJAU38148" then
print("Override Accepted!")
else
shell.run("server")
end
end

-- End of receiving

ID, message = rednet.receive()

if
message == "Upload" then
Upload()
elseif message == "Override" then
override()
elseif message == "Download" then
Download()
else
shell.run("server")

end









EDIT: I am always open to discussing this through private messages through Skype, or Google Talk.
Skype: Coaster5000
Gmail: Codyawsome10@gmail.com
Saugrim #6
Posted 18 October 2012 - 04:53 AM
Yes, there is. First things first, don't run the program again to continue it. You'll just overflow the stack that way. while loops are your friend. Second, you'd be better off keeping track of the state of each request by computer ID, then responding appropriately. You'll probably want to keep a table of computer IDs as the keys and the current state as the values. So, if a computer asks to download a file, it'd be stateTable[id] = "download". Then you'd check the current state whenever you got a packet and act accordingly. With that method, you can field as many requests as possible without needing time limits or such. And we don't mind large code, just use the spoiler tags around the code tags so that it won't take up huge amounts of space. You may wish to look up tutorials on using loops and on using tables in the Tutorials section of the forums if you're unfamiliar with either.

How might I do that in a code though? Like what would the server side code look like, and what would the user side look like?
I don't mess with the tables very often.
ChunLing #7
Posted 18 October 2012 - 06:51 AM
Start messing with them, they are the foundation of all data/function usage in lua.

for instance, you can store a series of functions in a table and then use something like "if table[rednetmessage] then table[rednetmessage]() end" This checks if the rednetmessage matches the index string for any of the functions in table, and executes the matching function if this is the case. If you use something like "t_mssg = {rednetmessage:find("^(%a+)(.*)")}" on the message string first, you can divide it into an initial command and an argument string, to eliminate the need to wait for additional replies to get the additional arguments, allowing you to execute the function immediately on receipt of the request.

"
Saugrim #8
Posted 18 October 2012 - 08:22 PM
.