Check latency on VOIP with pyaudio and TCP (Socket) [duplicate] - python

I have made a program that tells me if I am connected to the internet or not. Now I want it to ping www.google.com and show me the ping time in ms. I don't want to use any 3rd party software or download anything.
Edit:
My code is:
def is_connected():
try:
# see if we can resolve the host name -- tells us if there is
# a DNS listening
host = socket.gethostbyname(REMOTE_SERVER)
# connect to the host -- tells us if the host is actually
# reachable
s = socket.create_connection((host, 80), 2)
return True
except:
pass
return False
The above code just tells me if I am connected to the internet.
What I want is a simple way to show the ping of a website.
This is not a duplicate as it doesn't answer my question.

A ping is not the same thing as a HTTP connection! The first is a low level ICMP packet that is used to test connectiviy and find round-trip time mainly on a local network. It is generaly not used on broad internet, because for security reasons it is often blocked by firewall and external routers.
If you want to know the time necessary to establish the connexion to a server, do what you would in real world: look at your watch, do the job, look again at your watch to see elapsed time. In Python it gives
#import time
...
def connect_time():
try:
# see if we can resolve the host name -- tells us if there is
# a DNS listening
host = socket.gethostbyname(REMOTE_SERVER)
# connect to the host -- tells us if the host is actually
# reachable
before = time.clock() # from Python 3.3 and above use before = time.perf_counter()
s = socket.create_connection((host, 80), 2)
after = time.clock() # from Python 3.3 and above use after = time.perf_counter()
return after - before
except:
return -1

Related

Push notifications with minimal data usage

In my project, I want to call an action on a Raspberry Pi from the Internet. Somehow like that:
Visit webpage
Hit a button on the webpage
Raspberry pi executes a script
The difficult part is, that the raspberry pi only has a mobile Internet connection without a flatrate. So, sending and receiving data from/to the Raspberry Pi is costly.
So this is my question:
Which technologies and patterns can I use to send push notifications to the raspberry pi with minimal data usage?
Start off by creating or starting something that accepts incoming connections on your RPi. Something small as the below example would do:
#!/usr/bin/python
from socket import *
s = socket()
s.bind(('', 8001))
s.listen(4)
while 1:
ns, na = s.accept()
print(na,'sent you:',ns.recv(8192))
Now, the above example will only open a port on 8001 and then print whatever the other send sent to it.
On the server end, I suggest you setup a web server or something else that is easily accessible that can store an IP in a database/register somewhere.
Then, during boot of your RPi (pref after the networking service is started) go ahead and schedule:
curl https://your-server.eu/reg_ip.php > /dev/null 2>&1
Now, on the server your-server.eu:443, make sure req_ip.php saves the clients IP (client being your RPi) in a database somewhere.
Now, which ever application that you have that need to send out PUSH notifications can lookup the current IP of clients in the database and try to connect to port 8001 on those IP's and send whatever data you need.
Now two things:
A listening TCP socket (on the RPi) won't use up any data at all but will allow for incomming connections when needed.
If your IP changes on the RPi (which it probably will on a moving GSM/3G/4G network for instance), you need to do another curl request to your server. This however could easily be tied to a for instance ip monitor command and perform the curl request then.
tl;dr
Here's your chain:
Pi opens a listening socket -> Pi connects to HTTP(S) -> servers saves IP -> when server has something to send -> connect to last known IP on port X -> send data -> close connection
Enhancing further
Now, the HTTP header alone is quite big, in fact it's default 78 bytes of package data (TCP and IP headers usually isn't included in data rates, only the data being transferred is - in this case, HTTP data.). So what you could expand on is if you could use the simple example of a socket above on the server as well and just take the na[0] variable and send that to a database, that way you use literally 0 data-rate on your data subscription.
Only the actual data sent then later on from the server application as a "PUSH notification" would use up data.
In case your RPi is on a NAT based network (private network)
Seeing as the OP gets a 10.X.X.X address it's unlikely that a listening socket will do the trick.
Instead, what you could do is you could simply try and establish a connection and keep it open and have the server send data over any open socket when it has data.
Here's an extremely rough idea of how you could achieve it.
I kept it simple and stupid just to give an idea without solving the entire thing.
Again, the open socket between the client (RPi) and the Server won't use up any data until you actually send data over the channel.
You could in your server fetch data from a database that you want to send to the clients, you could do anything really. Since I don't know your goal I'll just leave it as it is for the time being.
Server:
#!/usr/bin/python
from socket import *
from threading import *
from time import time, sleep
from random import randint
class ClientThread(Thread)
def __init__(self, clients):
self.clients = clients
self.messages = []
Thread.__init__(self)
self.start()
def notify(self, message):
if type(message) is str: message = bytes(message, 'UTF-8')
self.messages.append(message)
def run(self):
while 1:
if len(self.messages) > 0:
m = self.messages.pop(0)
for client in self.clients:
self.clients[client]['sock'].send(m)
class RandomMessageGenerator(Thread):
def __init__(self, notify_func):
self.notify_func = notify_func
self.last = time()
Thread.__init__(self)
self.start()
def run(self):
while 1:
self.notify_func('Time since last update: ' + str(time() - self.last))
self.last = time()
sleep(randint(0,30))
client_list = {}
client_thread_handle = ClientThread(client_list)
random_generator = RandomMessageGenerator(client_thread_handle.nofity)
s = socket()
s.bind(('', 8001))
s.listen(4)
while 1:
ns, na = s.accept()
client_list[na] = {'sock' : 'ns'}
Client:
from socket import *
s = socket()
s.connect(('server', 8001))
while 1:
print(s.recv(8192))

Get ping time in python

I have made a program that tells me if I am connected to the internet or not. Now I want it to ping www.google.com and show me the ping time in ms. I don't want to use any 3rd party software or download anything.
Edit:
My code is:
def is_connected():
try:
# see if we can resolve the host name -- tells us if there is
# a DNS listening
host = socket.gethostbyname(REMOTE_SERVER)
# connect to the host -- tells us if the host is actually
# reachable
s = socket.create_connection((host, 80), 2)
return True
except:
pass
return False
The above code just tells me if I am connected to the internet.
What I want is a simple way to show the ping of a website.
This is not a duplicate as it doesn't answer my question.
A ping is not the same thing as a HTTP connection! The first is a low level ICMP packet that is used to test connectiviy and find round-trip time mainly on a local network. It is generaly not used on broad internet, because for security reasons it is often blocked by firewall and external routers.
If you want to know the time necessary to establish the connexion to a server, do what you would in real world: look at your watch, do the job, look again at your watch to see elapsed time. In Python it gives
#import time
...
def connect_time():
try:
# see if we can resolve the host name -- tells us if there is
# a DNS listening
host = socket.gethostbyname(REMOTE_SERVER)
# connect to the host -- tells us if the host is actually
# reachable
before = time.clock() # from Python 3.3 and above use before = time.perf_counter()
s = socket.create_connection((host, 80), 2)
after = time.clock() # from Python 3.3 and above use after = time.perf_counter()
return after - before
except:
return -1

How to set up a local DNS server in python

I am using windows 7 and python 2.7 I want to map 172.16.45.84 IP address to myapp.nobies.in without mapping in hosts file.
I have the required certificate to this hostname. I don't want to map in hosts file as it requires administrative privileges.
So, how to create a DNS python server for it, which can be shipped with my app.
see this post How can I do DNS lookups in Python, including referring to /etc/hosts? for how to do dns lookups in python.
You could do something like:
import socket
name = raw_input("hostname:")
if name == "mpapp.nobies.in":
print "172.16.45.84"
else:
print socket.gethostbyname(name)
This will perform normal DNS lookups unless you lookup "myapp.nobies.in" which will return 172.16.45.84
Note: this is not a functioning DNS server application. It is however a (very basic) nslookup-like command alternative. To make this an actual server you need to listen for DNS packets on port 53 (which will require admin rights as it's a privileged port. I guess you could use a higher one but you'd have to configure that on your DNS client too). Investigate socket server programming in python. Good reading here from the python docs:
https://docs.python.org/2/howto/sockets.html
and here:
https://docs.python.org/2/library/socket.html
I'd also suggest looking up dnslib and/or dnspython for parsing DNS packets
EDIT:
try this code as to get you going: (start in a command prompt and minimize)
#!/usr/bin/python
import socket
def resolve(name):
if name == "mpapp.nobies.in":
return "172.16.45.84"
else :
# you ought to add some basic checking of name here
return socket.gethostbyname(name)
host = ''
port = 50000
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
data = client.recv(size)
if data:
bits = data.split(":")
if bits[0] == 'h':
client.send(resolve(bits[1]))
client.close()
and use this as a client: (customize variables and run after you've started the server)
#!/usr/bin/python
import socket
### configure me ###
dns_server_ip = '127.0.0.1'
dns_server_port = 50000
query = 'mpapp.nobies.in' # change this to the hostname you want to lookup
### configure me ###
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((dns_server_ip,dns_server_port))
s.send('h:' + query)
data = s.recv(size)
s.close()
print data
Note: this is not really a dns server, it doesn't not understand dns packets it just takes a hostname string prefixed with 'h:' on port 50000 and returns an ip address. I hope this meets your needs.
Usage:
$ START "" .\dns-server.py
$ .\dns-client.py
172.16.45.84

Receiving and returning a packet after the function has ended

I have two functions. One sends a UDP packet to a port number and returns the port number if it gets a response. The second cycles through addresses calling the first function repeatedly incrementing the port number. It stops when a port number is returned. I'm basically spamming an IP to find which port number is being used.
All works well with very long time outs but I'm trying to speed up the rate at which I send my test packets. For example I might get a packet back from port 27018 even though the spam port function is sending to 27022. It then incorrectly reports that 27022 is the port to use. This happens even when I return the returned packet info from the first function since you can't tell the arguments which were used originally.
def check_port(s, serverip, serverport):
payload = "ffffffff54536f7572636520456e67696e6520517565727900".decode('hex')
s.sendto(payload, (serverip, serverport))
while 1:
try:
s.settimeout(0.1) # time to wait for response
d = s.recvfrom(1400)
data = d[0]
addr = d[1]
if len(data) > 1:
break
except socket.error:
return False
return addr[1]
def spam_ports(serverip):
s = serverComms.port_config()
start_highport = 27015
end_highport = 28015
start_lowport = 2299
end_lowport = 4000
port = start_highport
while check_port(s,serverip, port) == False:
port += 1
if port == end_highport:
port = start_lowport
if port == end_lowport:
return 'no query ports found in range'
else:
return check_port(s,serverip, port)
I really appreciate any help with this.
I think I know what happens.
It takes some time for the server to reply. If the delay is shorter than that, your application becomes confused. Let me explain:
You send packages to port 1000, 1001, 1002, ...
Say port 1010 produces a reply. But lets assume the server needs a full second to reply. Your application has progressed well bejond 1010 since the timeout is less then a second. By the time the reply arrives your application is already at, say, 1020. Now it looks like the received package is the result of sending something to 1020.
Possible approch
What you need is a way to know to which port a received reply belongs. Here it gets tricky:
Each package has a source and a destination port. With the packages you send the destination port is incremented. The source port is probably arbitrarly assigned. When the server answers it will send a package with an arbitrary source port and the destination port equal the source port of your package.
What you could do is check with the documentation and see how you can control the source port of the packages you're sending. With that you make sure that each sent package has a different source port. This identifies each package uniquely. Now you can use the destination port of the reply to know were it belongs to.
Then you can use, for example, two threads. One sending out packages and one receiving the answers. You keep a dict that maps my_source_port to server_port. The sender fills the dict and the receiver reads it. You can let the sender send as fast as it can, now timeout required. Once the sender is done you give the receiver thread a second or so to catch up.
port_map = {}
active_ports = []
def send(min, max):
for dest_port in range(min,max):
src_port = get_free_port()
port_map[src_port] = dest_port
send_package(src_port, dest_port, 'somedata')
def recv():
while True:
src_port, dest_port, data = receive_package()
port = port_map[dest_port]
active_ports.append(port)
This is not a working example, just the basic idea. The methods don't exist in that form, thread synchronization is missing and recv() would run forever, but it shows the basic idea.
You probably have to create a socket for each package you send.

Check if remote host is up in Python

How would I check if the remote host is up without having a port number? Is there any other way I could check other then using regular ping.
There is a possibility that the remote host might drop ping packets
This worked fine for me:
HOST_UP = True if os.system("ping -c 1 " + SOMEHOST) is 0 else False
A protocol-level PING is best, i.e., connecting to the server and interacting with it in a way that doesn't do real work. That's because it is the only real way to be sure that the service is up. An ICMP ECHO (a.k.a. ping) would only tell you that the other end's network interface is up, and even then might be blocked; FWIW, I have seen machines where all user processes were bricked but which could still be pinged. In these days of application servers, even getting a network connection might not be enough; what if the hosted app is down or otherwise non-functional? As I said, talking sweet-nothings to the actual service that you are interested in is the best, surest approach.
HOST_UP = True if os.system("ping -c 5 " + SOMEHOST.strip(";")) is 0 else False
to remove nasty script execution just add .strip(";")
-c 5
to increase the number of ping requests, if all pass than True
PS. Works only on Linux, on Windows always returns True
The best you can do is:
Try and connect on a known port (eg port 80 or 443 for HTTP or HTTPS); or
Ping the site. See Ping a site in Python?
Many sites block ICMP (the portocol used to ping sites) so you must know beforehand if the host in question has it enabled or not.
Connecting to a port tells you mixed information. It really depends on what you want to know. A port might be open but the site is effectively hung so you may get a false positive. A more stringent approach might involve using a HTTP library to execute a Web request against a site and see if you get back a response.
It really all depends on what you need to know.
Many firewalls are configured to drop ping packets without responding. In addition, some network adapters will respond to ICMP ping requests without input from the operating system network stack, which means the operating system might be down, but the host still responds to pings (usually you'll notice if you reboot the server, say, it'll start responding to pings some time before the OS actually comes up and other services start up).
The only way to be certain that a host is up is to actually try to connect to it via some well-known port (e.g. web server port 80).
Why do you need to know if the host is "up", maybe there's a better way to do it.
What about trying something that requires a RPC like a 'tasklist' command in conjunction with a ping?
I would use a port scanner. Original question states that you don't want to use a port. Then you need to specify which Protocol (Yes, this needs a port) you want to monitor: HTTP, VNC, SSH, etc. In case you want to monitor via ICMP you can use subprocess and control ping parameters, number of pings, timeout, size, etc.
import subprocess
try:
res = subprocess.Popen(['ping -t2 -c 4 110.10.0.254 &> /dev/null; echo $?'],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
out, err = res.communicate()
out = out.rstrip()
err = err.rstrip()
print 'general.connectivity() Out: ' + out
print 'general.connectivity() Err: ' + err
if(out == "0"):
print 'general.connectivity() Successful'
return True
print 'general.connectivity() Failed'
return False
except Exception,e:
print 'general.connectivity() Exception'
return False
In case you want a port scanner
import socket
from functools import partial
from multiprocessing import Pool
from multiprocessing.pool import ThreadPool
from errno import ECONNREFUSED
NUM_CORES = 4
def portscan(target,port):
try:
# Create Socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socketTimeout = 5
s.settimeout(socketTimeout)
s.connect((target,port))
print('port_scanner.is_port_opened() ' + str(port) + " is opened")
return port
except socket.error as err:
if err.errno == ECONNREFUSED:
return False
# Wrapper function that calls portscanner
def scan_ports(server=None,port=None,portStart=None,portEnd=None,**kwargs):
p = Pool(NUM_CORES)
ping_host = partial(portscan, server)
if portStart and portStart:
return filter(bool, p.map(ping_host, range(portStart, portStart)))
else:
return filter(bool, p.map(ping_host, range(port, port+1)))
# Check if port is opened
def is_port_opened(server=None,port=None, **kwargs):
print('port_scanner.is_port_opened() Checking port...')
try:
# Add More proccesses in case we look in a range
pool = ThreadPool(processes=1)
try:
ports = list(scan_ports(server=server,port=int(port)))
print("port_scanner.is_port_opened() Port scanner done.")
if len(ports)!=0:
print('port_scanner.is_port_opened() ' + str(len(ports)) + " port(s) available.")
return True
else:
print('port_scanner.is_port_opened() port not opened: (' + port +')')
return False
except Exception, e:
raise
except Exception,e:
print e
raise

Categories

Resources