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

Need help with "Server"

Started by jakendrick3, 13 January 2016 - 06:40 PM
jakendrick3 #1
Posted 13 January 2016 - 07:40 PM
My idea was to have a server that a client sends a ping to, and then the server returns with a message that indicates an unused channel to communicate on to avoid unwanted messages, but then I came across the problem that only 1 client could connect without some form of multi-tasking. Would multishell work for this and if not what do you suggest?
Lyqyd #2
Posted 13 January 2016 - 07:42 PM
There shouldn't be any problem with multiple clients connecting without needing to use multitasking. Please post your code, so we can provide guidance toward handling multiple clients.
jakendrick3 #3
Posted 13 January 2016 - 07:51 PM
I haven't started on it because it would probably need to be re-coded, but it's an update to a banking server software for me and my friends. As it stands I'm concerned multiple connections would get tangled due to the (novice) way that I've coded this.

http://pastebin.com/dC9um203

Here's the current version, if that helps. Sorry!
HPWebcamAble #4
Posted 14 January 2016 - 02:18 AM
To save users, you should use a table while the program is running, and a file for permanent storage.

A table is much faster to access than opening and reading a file.

When the program starts, load the table
When it stops (and at periodic intervals, if you'd like, for safety), save it to the file

Read more about tables here: http://www.lua.org/pil/2.5.html


In terms of communicating with the server, keep each action in one message

For example: when transferring money from one account to another, send a table like this:

local transferInfo = {
  action = "transfer",
  taker = "taker name",
  giverkey = "giverKey here",
  amount = 1,000,000,000

}

rednet.broadcast( transferInfo )

The server then receives this whole table and reads it to figure out what the client wants
Ideally, the server would then send back a 'success' or 'failure' message to the client.
TheOddByte #5
Posted 15 January 2016 - 01:00 AM
- snip -
Uhmm.. I'd just like to point out that it would be better to make the client program know what server it should connect to, instead of just sending the table to everyone.
Something like this for example

local host = 123


--# A method that waits for a message from the host to make sure it's up
local function isResponding()
    --# Try to get response from the server 5 times
    for i = 1, 5 do
        --# Send a message to the server so that it can later send one back
        rednet.send( host, {
            request = "ping";
        })
        --# Get response from the server
        local id, packet = rednet.receive( 1 )
        if id == host and type( packet ) == "table" and e[3]["response"] and e[3]["response"] == "pong" then --# Make sure that the id and message was valid
            return true
        end
    end
    return false
end


--# Check if the server is responding, if it isn't then print some error code or something
if isResponding() then
    --# the server is responding, do stuff
else
    print( "The server is not responding!" )
    error()
end

And if you want "multitasking" for rednet, I'd suggest you use os.pullEvent instead

local e = { os.pullEvent() } --# Wait for an event
if e[1] == "rednet_message" then --# The first parameter you're going to get is the event, it's always the event
    if e[2] == 1337 and e[3] == "1337" then --# The second parameter in this case is going to be the ID of the sender, and the third is going to be the message
        print( "4 1337 M3554G3 W45 R3C13V3D" )
    end

elseif e[1] == "key" --# Do something else if a key was pulled
    --# code here etc.
end

This part

function makeKey()
  a = math.random(0, 9)
  b = math.random(0, 9)
  c = math.random(0, 9)
  d = math.random(0, 9)
  e = math.random(0, 9)
  f = math.random(0, 9)
  g = math.random(0, 9)
  h = math.random(0, 9)
  i = math.random(0, 9)
  j = math.random(0, 9)

  newkey = a..b..c..d..e..f..g..h..i..j
  return newkey

end
could be shortened to this using a for loop

local function makeKey()
    local key = ""
    for i = 1, 10 do
        key = key .. tostring( math.random( 0, 9 ) )
    end
    return key
end

Something I'd really suggest is that you check out the following things
  • Tables
  • Loops
  • Event Handling
And because I see that you're trying to create a banking system I'd also suggest you check out some kind of encryption and hashing, because my guess is that noone wants to use a banking system that isn't secure :P/>
HPWebcamAble #6
Posted 15 January 2016 - 01:13 AM
it would be better to make the client program know what server it should connect to, instead of just sending the table to everyone.

Good point, my example used rednet.broadcast, though the message should be directed at a specific computer with rednet.send

Ideally, broadcast is only used when a client wants to find servers in range
Edited on 15 January 2016 - 12:14 AM
Ajt86 #7
Posted 15 January 2016 - 05:14 PM
Ideally, broadcast is only used when a client wants to find servers in range

Ideally, rednet shouldn't even be used (easy packet sniffing and predictably simple protocol).
TheOddByte #8
Posted 15 January 2016 - 08:41 PM
Ideally, rednet shouldn't even be used (easy packet sniffing and predictably simple protocol).
Or you know, you can use rednet as a wrapper and create your own network api that's a bit more secure.
valithor #9
Posted 15 January 2016 - 08:58 PM
Ideally, rednet shouldn't even be used (easy packet sniffing and predictably simple protocol).
Or you know, you can use rednet as a wrapper and create your own network api that's a bit more secure.

If you meant build your api on rednet, then it would still not be secure. When rednet.send is called it sends the message on 65533 no matter what "id" you tell it to send to. If you want the api to have any security at all, then you would need to use the modem api.
HPWebcamAble #10
Posted 15 January 2016 - 11:39 PM
Ideally, rednet shouldn't even be used (easy packet sniffing and predictably simple protocol).

Since jakendrick3 is just getting start with this program, I'd suggest getting the interface and server working first.
Secure networking is, arguably, more difficult than either of those. Rednet is an excellent API to use for early networking tests.

No, rednet isn't secure at all. I'd say it isn't supposed to be, its up to the user to implement any security.
Lyqyd #11
Posted 16 January 2016 - 01:08 AM
The correct way to go about better networking is to use the rednet function calls in the program for optimum interoperability, then provide a networking solution that transparently replaces the rednet functions to transport the data via its mechanisms, with a raw rednet fallback if it isn't installed on both ends.
Bomb Bloke #12
Posted 16 January 2016 - 01:17 AM
If you want the api to have any security at all, then you would need to use the modem api.

That won't prevent traffic sniffing. It'll make it harder to pinpoint the correct channel to listen on, but let's face it, it's not hard to rapidly open/close channels in a loop.

If you truly want any real level of security, you either make your network out of wired modems and prevent outside connections via plenty of warded blocks, or you implement encryption. All wireless transmissions can be tapped no matter which API you use.

Anyway, I suggest forgetting about security for now (let's face it, that's NOT a topic for novices) and using rednet with protocols. This is a simple way to filter out traffic that's not intended for your script, and it makes it easy for other scripts to filter out your traffic.

Rednet messages indicate the channels of their sender, making it fairly easy to figure out which system you're having a conversation with at any given time.