How to continue trying to attempt a connection if connection fails - python

(python)
So I have a basic connection that works fine as long as whatever I want to connect to is online. The code is turned into a standalone using pyinstaller. If whatever I want to connect to is offline, when the standalone program is run it gives me a "Failed to excecute script test" (test being name of the program). How can I make it so it continues trying to establish a connection until it succeeds? Here is what I attempted below.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
result = s.connect_ex((host,port))
if result == 0:
break
else:
sleep_for = random.randrange(1,10)
time.sleep( sleep_for )
pass
Func1()
Func2()
s.close()

The documentation for connect_ex says:
Like connect(address), 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)
That means that you still need to catch exceptions in order to infinitely retry to connect. In order to not make double work: processing connect_ex return value and catching exceptions, you can switch from using connect_ex to connect method and rewrite your code like this:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
try:
s.connect((host,port))
break
except socket.error:
sleep_for = random.randrange(1,10)
time.sleep( sleep_for )
pass
Func1()
Func2()
s.close()

Related

Treat try and except the same

I'm writing something that checks if a port is open, but modifying it to my use.
I set timeout for the check and if timeout reaches it raises socket.timeout exception, but I want a code block inside the try to also be invoked on socket.timeout:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
result = sock.connect_ex((check_server_ip, check_port))
if result == 0:
# act on open port
else:
# act on closed port
sock.close()
except socket.timeout:
# act on closed port
The code block I have on # act on closed port is long. I can create a function that has the code and call it on the else statement and socket.timeout exception, but I bet python has something more clever.
What can achieve this?
I don't think you need something clever or magical here. I looked at your code, then entered python -c "import this" in my terminal and saw this among the lines:
Flat is better than nested.
So, you don't need to create, set timeout and close a socket in the try ... except timeout - nothing throws timeout there:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
try:
result = sock.connect_ex((check_server_ip, check_port))
socket_connected = result == 0
except socket.timeout:
socket_connected = False
if socket_connected:
do_connected_stuff()
else:
do_disconnected_stuff()
sock.close()
However, the correctness of this code really depends on if do_connected_stuff() can throw socket.timeout and if do_disconnected_stuff() is a meaningful action in this case. If yes to all questions, then you've already got a pretty much optimal structure - at least without the full view of your system.

Sockets and functions

I have a big question I couldn't get answer from the web about
sockets in python.
I'm making a simple client program (python) based on socket:
Connecting to a server.
I would like to make a function that its purpose is just to try to connect to the server, otherwise the application will not work.
Because I had trouble with "global" socket variable across the whole class, I decided to make a local socket variable inside my main and pass it through all functions.
I wanted to make sure that I understand it 100% :
Should I return the socket from the function that's trying to connect to the server ( otherwise sleeps for 0.5 a second and tries again )
OR I don't need to return the socket at all and the socket variable itself will be updated ?
UPDATE
#will try to connect to the server
def try_connecting_to_server(socket_to_server):
connected = False
while not connected:
try:
socket_to_server.connect((HOST, PORT)) # connect to the server
connected = True
except:
print "couldn't connect to server, sleeping for 0.5 seconds"
time.sleep(0.5)
return socket_to_server
def main():
# start the socket to the server
socket_to_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # setup the socket for future use
try:
socket_to_server = try_connecting_to_server(socket_to_server)
handle_missions(socket_to_server) # pass the socket
except:
print "encountered an error"
finally:
socket_to_server.sendall(PROTOCOL_CLOSE_KEY)
socket_to_server.close()
if __name__ == "__main__":
main()
def try_connecting_to_server(socket_to_server):
connected = False
while not connected:
try:
socket_to_server.connect((HOST, PORT)) # connect to the server
connected = True
except:
print "couldn't connect to server, sleeping for 0.5 seconds"
time.sleep(0.5)
return socket_to_server
There is no reason for this function to return socket_to_server.
Since a socket object is mutable, any changes to it inside the function (e.g. connecting it to a server) are visible to the function which called it.
You can verify that by making this change in main():
returned_sock = try_connecting_to_server(socket_to_server)
if returned_sock is socket_to_server:
print "They refer to the exact same object!"
See How do I pass a variable by reference?

Python socket programming - exception handling

I'm working on a basic socket client program in python and I'm not totally sure how to handle exceptions. This is what I did up to now:
TCP_IP = '..............'
TCP_PORT = 4950
MESSAGE = "o3"
BUFFER_SIZE = 2048
data = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5.0)
try:
s.connect((TCP_IP, TCP_PORT))
except socket.error:
#write error code to file
s.close()
try:
s.sendall(MESSAGE)
except socket.error:
#write to file or whatever
s.close()
try:
data = s.recv(BUFFER_SIZE)
except socket.error:
#write to file or whatever
s.close()
finally:
s.close()
The code is working as I want, but I'm not sure if I should nest try/catch blocks or not? Should I put socket.socket into try/catch block too?
Second question, what will s.settimeout() do in my case? As far as I understood the documentation, it will throw an exception after 5 seconds, but for what? Just connect or will it do the same for sendall and recv?
Since you're doing exactly the same actions in all the exception blocks and catching the same socket.error exception, you could put s.connect, s.sendall and s.recv in the same try: block. Like so:
try:
s.connect((TCP_IP, TCP_PORT))
s.sendall(MESSAGE)
data = s.recv(BUFFER_SIZE)
except socket.error:
#write error code to file
finally:
s.close()
Note that since s.close is also in the finally section in your example, it will always get called, even after an exception has occurred. So you'd end up with another exception occurring when you try to close an already closed socket. By not putting it in the except block and only in finally, you can avoid that situation.
If you do intend to handle each error in a different way, then you can leave them separate as you already have. But make sure to break/return at the end of the exception block so that you don't try the next. It's done that way in the socket examples, by using a continue in the loop.
Nesting them would help if you wanted to do something different in the exception block. But if not you'd be repeating the except block every time. And if you wanted to do something different, when you exit the nested-trys, you wouldn't be certain of which level it has completed or raised an exception - would need to use flag values etc. to merely track that. So for your example of the same error handling code, at the very least, do something like this in your except block:
except socket.error as e:
socket_error_handler(e, s)
def socket_error_handler(exception, socket):
#write error code to file
etc.
Should I put socket.socket into try/catch block too?
They do that in the examples, linked above.
Apart from logging, you shouldn't really be doing the same exception handling at each stage. Probably need to handle those separately.
Part 2:
s.settimeout(5.0) sets the timeout for each socket operation, not just the first connect. Also implies that it's in blocking mode.

Python - is finally block necessary in socket operation?

I am a newbie to Python and currently doing some socket development. I am not very sure about the best practices of Python socket programming.
For example, in the following code, are the conn=None line and the finally block necessary? What is the best convention for this kind of operation?
#post('/relay/')
def relay():
conn = None # Do I need this line to ensure conn not to be undefined?
try:
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect(host_port)
conn.sendall(content)
except socket.error, se:
if se.errno == 61:
logger.error(...)
else:
logger.error(...)
abort(400, 'Error...')
finally: # Should this socket.close() task be in finally block? like Java?
if conn:
conn.shutdown(socket.SHUT_RDWR)
conn.close()
return ''
finally is typically used when you are working with some kind of connection (socket, database, etc) that is open, being operated on in the try and no matter what happens, should be closed after.
So yes, conn.close() should go in the finally block.
As for the conn=None, that could be required, but in your case it's not. Because if
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
fails, conn is never defined and it jumps to the finally block (because of the failure). However you check for if conn=None so it won't complain about trying to close a connection that is not defined because the if is skipped.

Killing a thread with a socket in it (python)

I am pretty new at this.I am trying to build a server(chat server)
Sorry for presenting such a messing code.
There are alot of things that i am going to change about this code.
but as of now i just need help with one thing:
when i start let say more then one cleints on this ...and then just close the client i get this message:
Unhandled exception in thread started by
i have tryed to kill the thread as you can see in many places in this code. but i don't know what i am doing wrong ..
i am new at this.
any syggestions on what i should do ?
#encoding: utf-8
import socket, random, time, thread, errno, traceback
print socket.gethostname()
print "current machines IP address: "+socket.gethostbyname(socket.gethostname())
host ="10.0.0.1"# raw_input("IP: ")
# = socket.gethostbyname(socket.gethostname())
port = 12345
print host
conn_list =[None]*10
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(10)
print "connected..\n\n\n\n"
def recv(conn):
while True:
try:
message = conn.recv(1024)
if "MESG" == message[1:5]:
message = message[6:].split(':')
name = str(conn)
conn_number = conn_list.index(conn)
conn_name = str(conn_number)
message = message[2]
reciever = message[0:1]
reciever = int(reciever)
for conn in conn_list:
if reciever == conn_list.index(conn):
conn.send(message)
print "Connection "+conn_name+" -----> "+str(reciever)+" :"+message+"\n"
#conn = findTheRightConnection(conn_list, conn_number)
break
else:
pass
except ValueError:
print "ValueError by %s" % (str(conn))
print conn.send("\nOpps you are not typing the correct connection number infront your message!")
except IOError:
bye(conn,conn_list)
print"Going to try to kill the thread here "
thread.quit()
thread.isAlive()
print "Still alive..."
except socket.error, v:
errorcode=v[0]
bye(conn,conn_list)
print"Going to try to kill the thread or here"
thread.quit()
thread.isAlive()
print "Still alive..."
except Exception, e:
traceback.print_exc()
finally:
thread.isAlive()
print"\nChanging the conn back to what it was... "
conn = findTheRightConnection(conn_list, conn_number)
def handle_connection(conn):
try:
recv(conn)
except socket.error, v:
errorcode=v[104]
bye(conn)
def bye(conn,conn_list):
i= 0
print "bye"
connectionName = str(conn_list.index(conn))
conn.close
conn_list = conn_list
print conn_list
for element in conn_list:
if element == conn:
conn_list[i] = None
break
i += i
print "Connection number "+connectionName+" is terminated"
print conn_list
return "Connection Terminated"
def welcome(conn,conn_list):
i = 0
for element in conn_list:
if element == None:
conn_list[i] = conn
print "Connection added in the conn_list on the slot %d" % (i)
print conn_list
return conn_list
else:
i = i+1
pass
print "The server if full! No more space left"
return conn_list
def findTheRightConnection(conn_list, number):
for conn in conn_list:
if number == conn_list.index(conn):
return conn
else:
pass
print "\nSomthing went wrong while trying to find the right connection in the method findTheRightConnection()"
return
while True:
conn, addr = sock.accept()
conn_list = welcome(conn,conn_list)
print "Got connection from : "+str(addr[0])+" by connection number: "+str(conn_list.index(conn))+"\n\n\n\n"
msg = "Welcome to the server!"
conn.send(":INFO:"+str(int(time.time()))+":"+str(len(msg))+":"+msg)
thread.start_new_thread(handle_connection, (conn,))
If you are still having trouble creating a instant messaging program in Python, you might be interested in this answer to another question.
Simple_Server.py is a minimal server implementation. A far more complex server with a variety of features can be provided on request. The complex server supports authentication, friends, private messaging, channels, filters, math evaluation, and admin controls.
MultichatClient.py is a port of a Java program written by a teacher from a networking class. The program must be run from the command line, and it must be given the server as an argument. You can use either the server's name on the network or its IP address.
Simple_Client.pyw is a more complicated client that does not require being started from the command line. When it starts, it will ask for server's name and try connecting to it while showing a progress dialog. The program will automatically try logging any errors to a file.
affinity.py is required for threadbox.py to run. (runs code on a specific thread regardless of origin)
threadbox.py is required for safetkinter.py to run. (metaclass clones classes to run using affinity)
safetkinter.py is required for Simple_Client.pyw to run. (makes tkinter safe to use with threads)

Categories