Network checker giving false negatives python - python

This code is able to detect whether the internet is disconnected or connected, and works mostly as I've tested it. The problem is occasionally it says internet disconnected and right after that it says internet connected. This has happened many times while I'm browsing the web, watching videos or whatever, the point being I know the internet is working.
I know the code's a bit of a mess. What's causing these false disconnects?
import win32com.client as w
import socket
s = w.Dispatch("SAPI.SpVoice")
try:
socket.setdefaulttimeout(5)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(("8.8.8.8", 53))
a = True
except Exception:
a = False
pass
while a == True:
while True:
try:
socket.setdefaulttimeout(5)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(("8.8.8.8", 53))
s.Speak("Internet connected")
break
except Exception:
continue
while True:
try:
socket.setdefaulttimeout(5)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(("8.8.8.8", 53))
continue
except Exception:
s.Speak("Internet disconnected")
break
while a == False:
while True:
try:
socket.setdefaulttimeout(5)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(("8.8.8.8", 53))
continue
except Exception:
s.Speak("Internet disconnected")
break
while True:
try:
socket.setdefaulttimeout(5)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(("8.8.8.8", 53))
s.Speak("Internet connected")
except Exception:
continue

You're connecting to google's DNS server at a rate of about 100 times per second, at least on my machine. I wouldn't be surprised if they occasionally refuse your connections, but I'm not willing to test this theory. Perhaps your machine is running out of ports at this rate? I have no idea how windows TCP stack would handle something like this.
Try adding a sleep into all of your loops to make sure you're not hammering them - testing your connection every couple of seconds should be fine.
Also, your original question is "Why is the socket failing to connect?" Well, catch the exception, and print so you'll know (or say it out loud :) )

Related

Python Socket Programming, other programs aren't connecting to the server

I am opening the same program multiple times (10 to be exact) and i they are all trying to solve the random number first. When they solve this number they open a server which all of the other same programs are listening to on separate threads waiting to connect and when they do finally connect i want them all to shutdown.
import random
import os
import socket
import threading
import time
host = '192.168.1.139'
port = 8011
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def verified():
print('Connection made successfuly')
time.sleep(10)
quit()
def network():
try:
s.connect(('192.168.1.135',8014))
f = s.recv(50)
finished = f.decode('utf-8')
if finished == 'completed':
quit()
except:
pass
def winner():
x = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
x.bind(('192.168.1.135', 8014))
x.listen(10)
con, address = x.accept()
con.send(bytes('completed', 'utf-8'))
def mine():
global guess
time.sleep(.000001)
guess = random.randint(0,1000)
print(guess)
tran = 500
while True:
mine()
if guess == 500:
print("Solved")
winner()
break;
else:
x = threading.Thread(target=network)
x.start()
For some reason it is connecting to the server but it isn't quitting the program, could this be because it is connecting to itself and exiting to fast? Please help, Thank You!
Actually, I was consfused, but apparently when the quit() is in a function it can't end the whole process, so what I would suggest you to do is to make the while loop with a variable that network would be able to change (or even use guess):
guessing = True
while guessing:
mine()
if guess == 500:
print("Solved")
winner()
break;
else:
x = threading.Thread(target=network)
x.start()
and change the network to:
def network():
try:
s.connect(('192.168.1.135',8014))
f = s.recv(50)
finished = f.decode('utf-8')
if finished == 'completed':
#quit()
global guessing
guessing = False
except:
pass
I saw that the two constants host and port were not used
Unfortunately the winner function is just accepting one answer
(she's a little introvert)
but we can solve that problem:
def winner():
x = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
x.bind(('192.168.1.135', 8014))
x.listen(10)
connected = 0
while connected < 10:
con, address = x.accept()
con.send(bytes('completed', 'utf-8'))
connected += 1
and yay, she is making friends
ok, but now she is in the outer world where she needs to talk to a lot of people
not just limited 10, so she goes to the bus stop (she's going home), she waits a little bit to see if someone will talk to her (for any reason), no one said anything for some time, so, she puts her airpods and starts listening to some good {insert here a music that a computer function likes to listen to}
So, to implement this:
def winner():
x = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
x.settimeout(5) # WAITS FOR FIVE SECONDS
x.bind(('192.168.1.135', 8014))
x.listen()
while True:
try:
con, address = x.accept()
con.send(bytes('completed', 'utf-8'))
except socket.timeout: # IF IN FIVE SECONDS, RECEIVES NO CONNECTION
break
the x.settimeout(5) will make the connections give an socket.timeout error if the time set (in case 5) is exceeded without any response of the other side.
now I remembered that using threading we could push clients to another function and "free" the queue of the clients, but I think that for this special case this solution is better

Threaded port scanner: Too many open files (after closing socket)

I wrote a little threaded port scanner, where I paid attention to closing the sockets after I'm done with them.
Despite closing the sockets, I'm getting Too many open files errors when I run it against a large number of target hosts (~ 12'000 hosts, and 5 ports, so a total of 60'000 sockets created/closed).
My understanding is that I should only encounter this error when closing the ports. I'm not really interested in the option that requires me to modify the number of open files my system can handle (recommend in other SO posts).
Full port scanner code below.
import socket
import itertools
from concurrent.futures import ThreadPoolExecutor, as_completed
def check_port(host, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1)
if sock.connect_ex((host, port)) == 0:
sock.close()
return host, port
sock.close()
return False
hosts = open('/tmp/hosts').read().splitlines()
ports = [80, 443, 8000, 8080, 8443]
with ThreadPoolExecutor(max_workers=100) as executor:
future_to_host_port = [
executor.submit(check_port, host, port)
for host, port in itertools.product(hosts, ports)
]
for future in as_completed(future_to_host_port):
try:
result = future.result()
if not result:
continue
print(result)
except socket.gaierror as e:
print(f'couldn\'t resolve')
except socket.timeout as e:
print(f'socket timeout')
except Exception as e:
print(type(e))
print(f'error {e}')
Not sure this is what's causing your specific problem, but your call to close() should be inside a finally block. From connect_ex's docs:
Like connect(address), but return an error indicator instead of raising an exception for errors returned by the C-level connect() call (other problems, such as “host not found,” can still raise exceptions).
Seems to me, if you're scanning 12,000 hosts, some of them don't exist and you leak a socket (or 5) for each of them.
Try this:
def check_port(host, port):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.settimeout(1)
if sock.connect_ex((host, port)) == 0:
return host, port
return False

Attempting to reconnect after a connection was refused - Python

I am trying to create a script that will, on error, attempt to reconnect again. But even after the receiving server has been started it still will not connect
send_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
try: #Cant get it to make connection after retrying
send_sock.connect((ip, port)) #always throws Con Refused when tryed
break
except socket.error:
print "Connection Failed, Retrying.."
time.sleep(1)
send_sock.send("hi")
edit: Corrected "try:" typo
Had this same issue myself, once I had worked it out it was actually quite a simple solution, all you need to do is create the send_sock before every connection attempt. Not sure why this fixes it but it does for me. Hope it does for you too.
while True:
try:#moved this line here
send_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
send_sock.connect((ip, port)) #no longer throws error
break
except socket.error:
print "Connection Failed, Retrying.."
time.sleep(1)
send_sock.send("hi")
Python socket will give you a error that should help with debugging your problem. For your example.
try:
send_sock.connect((ip, port))
except socket.error as error:
print("Connection Failed **BECAUSE:** {}").format(error)
Second of all you should almost never use while true: [...] as its just going to cause all sorts of problems. In this case you could put in a counter and loop on that break after X attempts.
While counter < 100:
try:
send_sock.connect((ip, port))
except socket.error as error:
print("Connection Failed **BECAUSE:** {}").format(error)
print("Attempt {} of 100").format(counter)
counter += 1
Check out the Python Docs on socket exceptions for more info.

Problems with socketing in IDLE

I'm trying to get a small socket communication set up on my own machine for testing purposes, but I keep getting errors like "[Errno 10053] An established connection was aborted by the software in your host machine" and "[Errno 10054] An existing connection was forcibly closed by the remote host"
The code for the server is
import socket, threading, Queue
class PiConn(threading.Thread, object):
def __init__(self, input_queue, output_queue):
threading.Thread.__init__(self)
self.input_queue = input_queue
self.output_queue = output_queue
self.HOST = ''
self.PORT = 8888
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
self.s.bind((self.HOST, self.PORT))
except socket.error, msg:
print "Binding socket failed, error message: " + msg[1]
def run(self):
self.s.listen(5)
while True:
try:
#trying to accept data
conn, addr = self.s.accept()
print "Connected to", addr
data = conn.recv(4096)
self.input_queue.put(data)
except Exception as e:
print e, "when trying to accept data"
break
try:
output = self.output_queue.get(False)
self.s.sendall(output)
print "Sent", output
except Queue.Empty:
pass
except socket.error as e:
print e, "when trying to send data"
input_queue = Queue.Queue()
output_queue = Queue.Queue()
conn = PiConn(input_queue, output_queue)
conn.start()
while True:
output_queue.put("This is sent by server")
try:
print input_queue.get(False)
except Queue.Empty:
pass
The code for the client is
import socket, threading, Queue
class GUIConn(threading.Thread, object):
def __init__(self, input_queue, output_queue):
threading.Thread.__init__(self)
self.input_queue = input_queue
self.output_queue = output_queue
self.PORT = 8888
self.PI_IP = "127.0.0.1"
try:
#Creates a socket
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
except socket.error, msg:
print 'Socket creating failed, error message:' + str(msg[1])
self.s.connect((self.PI_IP, self.PORT))
def run(self):
while True:
try:
#Trying to send data
output = self.output_queue.get(False)
self.s.sendall(output)
except Queue.Empty:
pass
except socket.error as e:
print e
try:
#trying to accept data
data = self.s.recv(4096)
self.input_queue.put(data)
except Exception as e:
print e
break
input_queue = Queue.Queue()
output_queue = Queue.Queue()
conn = GUIConn(input_queue, output_queue)
conn.start()
while True:
output_queue.put("This is sent by client")
try:
print input_queue.get(False)
except Queue.Empty:
pass
To test it, I start 2 IDLE shells, run the server, and then the client.
Any clue as to what I'm doing wrong? I'm fairly new at sockets, and I've been struggling with this all day.
Thanks in advance!
Your initial problem is caused by known issues IDLE has when working with threads.
See here and here for example.
I'm not aware of any workaround. Try running your code from terminal instead.
As to the other errors you're getting, if you post them, we can try and assist.
warning, big wall of text, read all of it before commenting
there is a huge number of problem with this small amount of code
first, the most obvious is the 'busy' loops that will use up all 100% of the cpu, not only that, it will also slowly use up all the ram as well cause you set the blocking for the queue.get to be False
you could have set it to True and it would have waited until there something and once it get that, it would loop back to the top and put another one of "This is sent by client" thus solving both the busy loop and ram usage problem
while True:
output_queue.put("This is sent by client")
try:
print input_queue.get(False) # here
except Queue.Empty:
pass
second, the way you reply/send data from the server to the client isn't through the main listening socket but the socket that is return from the self.s.accept()
so self.s.sendall(output) in the server should have been conn.sendall(output)
third, in the client code, there a chance that self.output_queue.get(False) would error with Queue.Empty and thus pass using the try and except and ended up in the blocking recv
and both the server and client would both be listening and waiting for each other to send something
fourth, self.s.accept() is blocking, after one loop in the server, it would be stuck waiting for another client while the client would send the data then end up waiting for some data
lastly, about those error you said, i can't reproduce them at all, if i have to guess, i say those error are cause by your firewall or the server isn't running (fail to bind) or something else, see here: No connection could be made because the target machine actively refused it
also, you could try a different port and maybe the first two example on this site to check if there is something weird causing problem, if those example doesn't work then there is a problem with your computer, https://docs.python.org/release/2.5.2/lib/socket-example.html

Test a pair of network sockets at the same time

I have an app X that can run on either of two computers, but on no more than one at once. I have another app Y, written in Python, that given the two possible ip addresses needs to find out which computer is running app X (if any). I've partially solved this by having a UDP service that listens on a port and responds with a 'Hello' whenever it receives some data. The client can try and send data to the app X port on each address and if it gets a response, I know the application is running on that computer.
My code so far looks like this:
def ipaddress(self):
"""Test which side responds on the status port."""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.settimeout(5)
s.sendto("status", (ADDR_A, PORT))
s.recvfrom(1024)
except socket.timeout:
try:
s.sendto("status", (ADDR_B, PORT))
s.recvfrom(1024)
except:
pass
else:
return ADDR_B
else:
return ADDR_A
finally:
s.close()
return None
The problem with this function is that it's called periodically whenever I want to talk to the computer running app X. It will always test ADDR_A first, and if it's not running app X then I have to wait for the socket to timeout before trying ADDR_B. Although it doesn't happen often app X could have switched computers whenever I come around trying again.
Is there a better way? I'm wondering if it's possible to connect to both computers in parallel and return as soon as one responds? Or should I cache which ip address responded first last time the function was called? How would I code these or other ideas?
Thanks.
EDIT: Here is my revised code using select:
def ipaddress(addr_a, addr_b, timeout=5):
"""Test which side responds on the status port."""
# Create UDP sockets for each address
socks = [ socket.socket(socket.AF_INET, socket.SOCK_DGRAM),
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
]
# Send some data to each socket
for sock, addr in zip(socks, (addr_a, addr_b)):
sock.connect(addr) # do explicit connect so getpeername works
sock.send("status")
# Wait for the first to respond if any
while socks:
waiting = select.select(socks, [], socks, timeout)[0]
if waiting:
for sock in waiting:
try:
data = sock.recv(1024)
if data:
return sock.getpeername()[0]
except Exception, e:
# Occasionally get [Errno 10054] which means socket isn't really
# available, so see if other responds instead...
socks.remove(sock)
else:
break # timeout occurred
return None
You should look at select.select() which provides exactly the capability you are looking for to look at the two computers in parallel.

Categories

Resources