In this tutorial, we will show how to calculate the distance between 2 IPs using geographical coordinates provided by any IP2Location database, except DB1, DB2, DB3, DB3 and DB7, as you can see at https://www.ip2location.com/databases
The programming language for this tutorial is BASH and you have to know a little scripting. The prerequisites for running this tutorial are:
- You must have any distribution of Linux as Operation System
- You must have Bash as shell
- You must have bc installed (It comes by default with the majority of distributions)
- You must compile a simple demo program similar with the one from the following link:https://www.ip2location.com/developers/c which just outputs latitude and longitude for one IP. The code is written in C:
#include "IP2Location.h" int main(int argc,char**argv) { if (argc!=3) { fprintf(stderr,"%s BinFile IP\n",argv[0]); return 0; } char *szBinFile=argv[1]; char *szIp=argv[2]; IP2Location *IP2LocationObj = IP2Location_open(szBinFile); if (IP2LocationObj==NULL) { fprintf(stderr,"Obj is NULL\n"); return 0; } IP2LocationRecord *record = IP2Location_get_all(IP2LocationObj, szIp); if(record==NULL) { fprintf(stderr,"Record is NULL\n"); } printf("%f,%f\n", record->latitude, record->longitude); IP2Location_free_record(record); IP2Location_close(IP2LocationObj); return 0; }
- The following steps are necessary to compile this program:
- Step 1: Download IP2Location_C_Library and follow the steps to compile and install it.
- Step 2: Save the demo program shown above as ip2locationLatLong.c
- Step 3: Compile it as ip2locationLatLong .
- Step 4: You can run the program: ./ip2locationLatLong db5.bin 89.89.89.89
This tutorial has four steps for implementing the BASH script, which calculates the distance between 2 IPs and one for testing.
R = 6371; // km distance = Math.acos(Math.sin(lat1)*Math.sin(lat2) + Math.cos(lat1)*Math.cos(lat2) * Math.cos(lon2-lon1)) * R;
Step 1. For the beginning of this tutorial, we will start by showing you how to calculate the distance between any 2 points knowing the latitude and longitude of the points. The formula uses The Spherical Law of Cosines because nowadays, float is very precise. The formula for this task is the following: (The code is taken from http://www.movable-type.co.uk/scripts/latlong.html).
Step 2. We can implement this formula in Bash in the following way using bc: (bc is a precision calculator language)
EARTH_RADIUS="6371" PI="3.141592653589793" #Converts degrees in radians ( deg2rad() { bc -l <<< "$1 * $PI / 180" } #Converts radians in degrees rad2deg() { bc -l <<< "$1 * 180 / $PI" } #Calculates acos($radians), because bc has no acos function acos() { bc -l <<<"$PI / 2 - a($1 / sqrt(1 - $1 * $1))" } #Applies The Spherical Law of Cosines for finding distance between 2 coordinates getDistance() { delta_lat=$(bc <<<"$LAT2 - $LAT1") delta_lon=$(bc <<<"$LONG2 - $LONG1") LAT1=$(deg2rad "$LAT1") LONG1=$(deg2rad "$LONG1") LAT2=$(deg2rad "$LAT2") LONG2=$(deg2rad "$LONG2") delta_lat=$(deg2rad "$delta_lat") delta_lon=$(deg2rad "$delta_lon") DISTANCE=$(bc -l <<< "s($LAT1) * s($LAT2) + c($LAT1) * c($LAT2) * c($delta_lon)") DISTANCE=$(acos "$DISTANCE") DISTANCE=$(bc -l <<< "$DISTANCE * $EARTH_RADIUS") DISTANCE=$(bc <<<"scale=4; $DISTANCE / 1") }
Step 3. In this step, we will show how to combine the simple demo program with the BASH script and how to find the distance between two IPs, which is the goal of this tutorial. For this step, we must parse the output of ip2locationLatLong program with cut.
#!/bin/bash #This is the location of bin file #You must modify for your system BIN_FILE="db5.bin" EARTH_RADIUS="6371" PI="3.141592653589793" #Converts degrees in radians ( deg2rad() { bc -l <<< "$1 * $PI / 180" } #Converts radians in degrees rad2deg() { bc -l <<< "$1 * 180 / $PI" } #Calculates acos($radians), because bc has no acos function acos() { bc -l <<<"$PI / 2 - a($1 / sqrt(1 - $1 * $1))" } #Applies The Spherical Law of Cosines for finding distance between 2 coordinates getDistance() { delta_lat=$(bc <<<"$LAT2 - $LAT1") delta_lon=$(bc <<<"$LONG2 - $LONG1") LAT1=$(deg2rad "$LAT1") LONG1=$(deg2rad "$LONG1") LAT2=$(deg2rad "$LAT2") LONG2=$(deg2rad "$LONG2") delta_lat=$(deg2rad "$delta_lat") delta_lon=$(deg2rad "$delta_lon") DISTANCE=$(bc -l <<< "s($LAT1) * s($LAT2) + c($LAT1) * c($LAT2) * c($delta_lon)") DISTANCE=$(acos "$DISTANCE") DISTANCE=$(bc -l <<< "$DISTANCE * $EARTH_RADIUS") DISTANCE=$(bc <<<"scale=4; $DISTANCE / 1") } #Retrieves the coordinates for the 2 IPs getCoordinate() { #Call ip2locationLatLong for $IP1 output=$(./ip2locationLatLong "$BIN_FILE" "$IP1") #Parse the output to obtain both coordinates LAT1=$(echo "$output" | cut -d ',' -f 1) LONG1=$(echo "$output" | cut -d ',' -f 2) #Call ip2locationLatLong for $IP2 output=$(./ip2locationLatLong "$BIN_FILE" "$IP2") #Parse the output to obtain both coordinates LAT2=$(echo "$output" | cut -d ',' -f 1) LONG2=$(echo "$output" | cut -d ',' -f 2) } #Prints the coordinates for the 2 IPs printCoordinate() { echo "Coordinates for $IP1: ($LAT1,$LONG1)" echo "Coordinates for $IP2: ($LAT2,$LONG2)" } #Checks if the coordinates are not empty validCoord() { ip=$1 coord=$2 if [ "$coord" = "" ]; then echo "$ip is not a good address" exit 0 fi } #Checks if the script is run with 2 parameters if [ $# -ne 2 ]; then echo "Usage: $(basename $0) IP1 IP2" exit 0; fi IP1=$1 IP2=$2 #Retrieves and validates the coordinates getCoordinate printCoordinate validCoord $IP1 $LAT1 validCoord $IP1 $LONG1 validCoord $IP2 $LAT2 validCoord $IP2 $LONG2 #Calculate and print the distance getDistance echo "Distance between $IP1 and $IP2 is $DISTANCE km"
Step 4. You can now run the script.
bash getDistance.sh 89.89.89.89 30.13.56.34 |
Step 5. You can validate the output distance running the script from http://www.movable-type.co.uk/scripts/latlong.html which calculates the distance between two points.