You must not have my latest. Keep in mind that this function requires a CIDR
notation or else the IP and subnet mask. Nothing can calculate the subnet with
only an IP address.
Bob S
function IPCalc theIPAddress, theSubnetMask
/* IPCalc yyy
Syntax:
IPCalc theIPAddress, [theSubnetMask]
Examples:
Description:
Derive Internet values from either CIDR notation in the IPAddress
or a standard IP and subnet mask
Input:
. theIPAddress - the IP address in CIDR notation
or
. theIPAddress - a standard IP address and
. theSubNetMask - a standard subNetMask
Returns an array of the following values:
. bcastaddr
. cidraddr
. cidrdepth
. firstaddr
. ipaddress
. lastaddr
. subnetaddr
. subnetmask
. usablecount
Returns a string beginning with ERROR: if the parameters are out of range
Check that the returned value is an array to see if there was an error
Source:
Bob Sneidar, [email protected]
IPCalc */
set the itemdelimiter to "."
-- check parameters
-- the IP address must be 4 octets of numbers
if the number of items of theIPAddress <>4 \
or the last char of theIPAddress is "." \
or ".." is in theIPAddress then
return "ERROR: The IP Address must be in the form:" & cr & \
"'nnn.nnn.nnn.nnn' or 'nnn.nnn.nnn.nnn/nn'. (ipaddress = '" &
theIPAddress & "')"
end if
-- initial setup
set the numberformat to "00000000"
-- detemine format
if theIPAddress contains "/" then
put offset("/", theIPAddress) into theCIDRDelim
put char theCIDRDelim +1 to -1 of theIPAddress into theCIDRDepth
-- CIDR depth must be a WHOLE number
put cleanString(theCIDRDepth) into theCIDRDepth
if theCIDRDepth is not a number then
return "ERROR: The CIDR Depth must be a number between 0 and 32. " & \
"(CIDRDepth = '" & theCIDRDepth & "')"
end if
put charx("1", theCIDRDepth) & charx("0", 32-theCIDRDepth) into
theBinSubnetMask
put baseconvert(char 1 to 8 of theBinSubnetMask, 2, 10) into item 1 of
theSubnetMask
put baseconvert(char 9 to 16 of theBinSubnetMask, 2, 10) into item 2 of
theSubnetMask
put baseconvert(char 17 to 24 of theBinSubnetMask, 2, 10) into item 3 of
theSubnetMask
put baseconvert(char 25 to 32 of theBinSubnetMask, 2, 10) into item 4 of
theSubnetMask
put char 1 to theCIDRDelim -1 of theIPAddress into theIPAddress
else
-- subnet mask octets must be 4 numbers between 0 and 255
-- and all octets after the first octet less than 255 must be 0
if the number of items of theSubnetMask <>4 \
or the last char of theSubnetMask is "." \
or ".." is in theSubnetMask then
return "ERROR: The Subnet Mask must be in the form:" & cr & \
"'nnn.nnn.nnn.nnn' (subnetmask = '" & theSubnetMask & "')"
end if
put false into mustBeZero
repeat for each item theOctet in theSubnetMask
if theOctet <0 or theOctet >255 then
return "Each octet in the subnet mask must be a number between 0
and 255. " & \
"(subnetmask = '" & theSubnetMask & "')"
end if
if mustBeZero and theOctet >0 then
return "ERROR: All octets after an octet less than 255 must be 0. "
& \
"(subnetmask = '" & theSubnetMask & "')"
end if
if theOctet <255 then
put true into mustBeZero
end if
end repeat
-- convert the subnet mask to binary
put 0 into whichOctet
repeat for each item theOctet in theSubnetMask
add 1 to whichOctet
-- subnet mask must contain only 4 octets
if whichOctet >4 then
return "ERROR: The Subnet Mask must contain 4 numbers between 0 and
255 " & \
"separated by periods. (subnetmask = '" & theSubnetMask & "')"
end if
put value(baseconvert(theOctet, 10, 2)) after theBinSubnetMask
end repeat
put offset("0", theBinSubnetMask) -1 into theCIDRDepth
end if
-- CIDR depth must be between 0 and 32
if theCIDRDepth <0 or theCIDRDepth >32 then
return "ERROR: The CIDR Depth must be between 0 and 32. " & \
"(CIDRDepth = '" & theCIDRDepth & "')"
end if
-- All octets of the IP address must be between 0 and 255
repeat for each item theOctet in theIPAddress
if theOctet is empty or theOctet < 0 or theOctet > 255 then
return "ERROR: Each IP Address octet must be a number between 0 and
255. " & \
"(ipaddress = '" & theIPAddress & "')"
end if
end repeat
-- convert the ip address to binary
put 0 into whichOctet
repeat for each item theOctet in theIPAddress
add 1 to whichOctet
put baseconvert(theOctet, 10, 2) into theBinValue
add 0 to theBinValue
put theBinValue after theBinIPAddress
end repeat
-- calculate the binary subnet address
put char 1 to theCIDRDepth of theBinIPAddress into theBinNetworkAddr
put char theCIDRDepth +1 to -1 of theBinIPAddress into theBinNodeAddr
put theBinNodeAddr into theBinSubnetNodeAddr
set the numberformat to "0"
replace "1" with "0" in theBinSubnetNodeAddr
put theBinNetworkAddr & theBinSubnetNodeAddr into theBinSubnetAddr
-- convert the binary subnet address to decimal
put baseconvert(char 1 to 8 of theBinSubnetAddr, 2, 10) into item 1 of
theSubnetAddr
put baseconvert(char 9 to 16 of theBinSubnetAddr, 2, 10) into item 2 of
theSubnetAddr
put baseconvert(char 17 to 24 of theBinSubnetAddr, 2, 10) into item 3 of
theSubnetAddr
put baseconvert(char 25 to 32 of theBinSubnetAddr, 2, 10) into item 4 of
theSubnetAddr
-- calculate the first usable IP address
put theSubnetAddr into theFirstAddr
add 1 to item 4 of theFirstAddr
-- calculate the binary broadcast address
put theBinNodeAddr into theBinBcastNodeAddr
replace "0" with "1" in theBinBcastNodeAddr
put theBinNetworkAddr & theBinBcastNodeAddr into theBinBcastAddr
-- convert the binary broadcast address to decimal
put baseconvert(char 1 to 8 of theBinBcastAddr, 2, 10) into item 1 of
theBcastAddr
put baseconvert(char 9 to 16 of theBinBcastAddr, 2, 10) into item 2 of
theBcastAddr
put baseconvert(char 17 to 24 of theBinBcastAddr, 2, 10) into item 3 of
theBcastAddr
put baseconvert(char 25 to 32 of theBinBcastAddr, 2, 10) into item 4 of
theBcastAddr
-- calculate the last usable IP address
put theBcastAddr into theLastAddr
subtract 1 from item 4 of theLastAddr
-- calculate the number of usable addresses
-- put item 4 of theLastAddr - item 4 of theFirstAddr +1 into theAddrCount
put baseconvert(theBinBcastNodeAddr, 2, 10) -1 into theAddrCount
-- calculate the CIDR notation
put theIPAddress & "/" & theCIDRDepth into theCIDRAddr
-- create array
put theIPAddress into ipdata ["ipaddress"]
put theSubnetMask into ipdata ["subnetmask"]
put theSubnetAddr into ipdata ["subnetaddr"]
put theFirstAddr into ipdata ["firstaddr"]
put theBcastAddr into ipdata["bcastaddr"]
put theLastAddr into ipdata ["lastaddr"]
put theCIDRDepth into ipdata ["cidrdepth"]
put theAddrCount into ipdata ["usablecount"]
put theCIDRAddr into ipdata ["cidraddr"]
return ipdata
end IPCalc
> On Oct 27, 2016, at 17:58 , Richard Gaskin <[email protected]> wrote:
>
> Thanks, Alex. I may need something more refined later on, but for now my
> modest needs appear to be well met through simple brute force:
>
> At the moment this is for some network tools for students to use in a
> classroom. Ideally there would be no Internet connection, just a local
> network of a small number of devices all using a single wifi router.
>
> I had experimented briefly with a UDP broadcast, but ran into an issue in
> which it seemed the server wasn't receiving the message.
>
> Before spending more time on that I tried a different tack with TCP.
>
> With Bob's IPCalc function I'm able to get the first and last addresses of
> the local subnet. His function needs the local IP and subnet mask, which can
> be obtained on Mac and Linux with a shell call to ifconfig, and on Win with
> ipconfig.
>
> Armed with that I just attempt a TCP connection to each device in turn,
> looking for a specific reply. When I get what I expect, I know I've reached
> my app on the other machine. Takes less than a second to scan the network.
>
> Done in a few minutes' work.
>
> Of course this won't do much for mobile devices (how do I get the local
> address on iOS and Android without shell?), but since UDP is off the table
> there anyway I'm no worse off, and can at least get started with laptops and
> Raspberry Pis happily talking to one another...
>
> --
> Richard Gaskin
> Fourth World Systems
>
>
> Alex Tweedly wrote:
>
>> it might help if you were to more precisely describe the problem you are
>> seeking to solve.
>>
>> If you need to discover all/any/arbitrary listeners - then "what Bob said".
>>
>> If you need to discover listeners for a specific port/service provided
>> by some other apps/servers in a standard way - then "what Monte said".
>>
>> If you need to discover instances of "your own" server on the LAN, then
>> there may be an other solution..... depending on how well defined "my
>> LAN" is.
>>
>> Basically,
>>
>> - every server listens for UDP packet on some port
>>
>> - client sends a broadcast UDP request to that port
>>
>> - servers respond.
>>
>> This assumes that you can *reliably* depend on your LAN being a single
>> subnet, that your LAN is not too huge :-), that all servers are within
>> your control and you can add such a listener to them, etc.
>>
>> NB - this is only a solution for desktops (only they can send broadcasts).
>>
>> For ios you can use mergSomething :-)
>>
>> For Android, afaik there isn't anything to allow broadcast transmission,
>> so I think your only solution for now is to move to a
>> broadcast/advertisement approach - servers (currently desktop only, you
>> said) must advertise their service, and Android clients can listen for
>> such adverts and thus learn where the service is available. This is only
>> feasible if you know of limits on the number of servers & services - or
>> (for-android as-client) if you are willing to add significant complexity
>> and have proxy-servers handle it for you; you can do that in an
>> automatic way (i.e. no configuration needed) but it is complex.
>>
>> Don't even start down that road unless you need this for Android before
>> the timeframe for either bonjour or sockets on android.
>>
>> (But if you do want to go down that road, get in touch I'd be happy to
>> collaborate)
>>
>> -- Alex.
>>
>>
>> On 27/10/2016 22:12, Richard Gaskin wrote:
>>> I'd like to have an app automatically discover and attempt connection
>>> to other devices on my LAN.
>>>
>>> Looking through the list archives I can find a few half-solutions, but
>>> not one which works well across the platforms LC supports (Mac, Win,
>>> Linux, iOS, Android).
>>>
>>> At this time the only things listening on a port will be desktop
>>> computers, but I still need to be able to connect with them from any
>>> other device on the local network, and down the road I may want to
>>> allow even handheld devices to take on an accept role.
>>>
>>> Any robust, tested solutions available?
>>>
>
>
> _______________________________________________
> use-livecode mailing list
> [email protected]
> Please visit this url to subscribe, unsubscribe and manage your subscription
> preferences:
> http://lists.runrev.com/mailman/listinfo/use-livecode
_______________________________________________
use-livecode mailing list
[email protected]
Please visit this url to subscribe, unsubscribe and manage your subscription
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode