I haven't tested that yet, but if the connection will not be executed, will this last sentence be printed?
def connect_to():
print(f"[*] Connecting to {receiver_ip}:{receiver_port}")
socket.connect((receiver_ip, receiver_port))
print(f"[+] Connected")
How can I check if I connected properly and make a proper if statement?
When a socket fails to connect, it will raise a socket.error exception. You can catch that specific error using some error handling techniques in Python.
import socket
def connect(ip, port):
s = socket.socket()
try:
print(f"Connecting to {ip}:{port}")
s.connect((ip, port))
except socket.error as msg:
print(f"Failed to connect: {msg}")
else:
print(f"Successfully connected to {ip}:{port}")
How can I check if I connected properly and make a proper if statement?
The except block will be executed if the specified error is caught in the try block. On the other hand, the else block will be executed when no errors were raised or handled. You can view the except block as "if error" and the else block as "if not error".
Alternatively, you can catch an error and re-raise it with your custom message.
import socket
def connect(ip, port):
s = socket.socket()
try:
print(f"Connecting to {ip}:{port}")
s.connect((ip, port))
except socket.error as msg:
raise socket.error(f"Failed to connect: {msg}")
print(f"Successfully connected to {ip}:{port}")
By catching and re-raising, you don't have to use the else block anymore.
Use try except to catch the errors and if the connection is successful
Related
I'm writing test script for a TCP Server in Python 3.8.
The script worka well, but now I'm tring to implemente a more efficient error catching in order to identify timeout error.
To do that I started to catch the errors and the timeout error for the socket connect.
This is my SocketConnect function:
def SocketConnect( host, port ):
global socketHandle
opResult = errorMessagesToCodes['No Error']
# Set Socket Timeout
socketHandle.settimeout(1)
logging.debug("Connect")
try:
socketHandle.connect((host, port))
except socketHandle.error as e:
opResult = errorMessagesToCodes['Socket Error']
logging.error("!!! Socket Connect FAILED: %s" % e)
return opResult
The socket handler is valid and, in order to test the timeout, I disable the server.
After one second after the connect the code goes to the except but I get this error:
socket.connect((host, port))
socket.timeout: timed out
During handling of the above exception, another exception occurred:
except socket.error as e:
AttributeError: 'socket' object has no attribute 'error'
Is there something missing?
Because I don't understand why socket object ha no attribute error. I think this is a standard error for socket interface.
Thanks in advance for the help.
UPDATE:
I tried to do a basic test (starting from a blank project): only a socket create and a socket connect (with a server not in listening mode) to simulate a timeout.
This is the code:
import socket
import logging
try:
socketHandle = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socketHandle.error as e:
logging.error("Socket Create FAILED: %s" % e)
socketHandle.settimeout(1)
try:
socketHandle.connect(('localhost', 2000))
except socketHandle.error as e:
logging.error("!!! Socket Connect FAILED: %s" % e)
The connect goes into timeout but I still get the error:
except socketHandle.error as e:
AttributeError: 'socket' object has no attribute 'error'
I really don't know what is happening.
UPDATE 2:
I made some other tests, and if I use the try-catch inside the connect function I get the error but if I use the try catch in the main a did not get any error.
Best regards,
Federico
The error is due to you redefining the module name socket; which is what contains socket.error. You are trying to access module level constants (in this case error from the socket module), from a socket object. You could also tighten the error handling to only catch a timeout. This may be needed anyhow, as it appears socket.error does not cover socket.timeout. Changing your socket name should solve the issue:
def SocketConnect(socx, host, port ):
opResult = errorMessagesToCodes['No Error']
# Set Socket Timeout
socx.settimeout(1)
logging.debug("Connect")
try:
socx.connect((host, port))
except socket.timeout as e:
opResult = errorMessagesToCodes['Socket Error']
logging.error("!!! Socket Connect FAILED: %s" % e)
return opResult
I have the following code, which is self explanatory:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host, port)
s.send("some data")
# don't close socket just yet...
# do some other stuff with the data (normal string operations)
if s.stillconnected() is true:
s.send("some more data")
if s.stillconnected() is false:
# recreate the socket and reconnect
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host, port)
s.send("some more data")
s.close()
How do I implement s.stillconnected()
I do not wish to recreate the socket blindly.
If the server connection is no longer alive, calling the send method will throw an exception, so you can use a try-exception block to attempt to send data, catch the exception if it's thrown, and reestablish the connection:
try:
s.send("some more data")
except:
# recreate the socket and reconnect
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host, port)
s.send("some more data")
EDIT: As per #Jean-Paul Calderone's comments, please consider using the sendall method, which is a higher level method that sends all the data or throws an error, instead of send, which is a lower level method that does not guarantee the transmission of all the data, OR use higher level modules like an HTTP library that can handle socket lifecycles.
I've had good results with this variant to check if a socket is closed (negate the result if you want to check if it's still connected):
import logging
import socket
logger = logging.getLogger(__name__)
def is_socket_closed(sock: socket.socket) -> bool:
try:
# this will try to read bytes without blocking and also without removing them from buffer (peek only)
data = sock.recv(16, socket.MSG_DONTWAIT | socket.MSG_PEEK)
if len(data) == 0:
return True
except BlockingIOError:
return False # socket is open and reading from it would block
except ConnectionResetError:
return True # socket was closed for some other reason
except Exception as e:
logger.exception("unexpected exception when checking if a socket is closed")
return False
return False
I am new to Python and facing some issues with exception handling.
When I create a socket and connect it to an IP/port, I want to handle the socket exceptions and not display Python errors on console. I did that with the help of try and except.
try:
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((self.host, self.port))
except error:
print 'Socket Error'
But I still get the error printed on console
error: uncaptured python exception, closing channel <SClient 20.0.0.1:5000 at 0x7fe94e0e2e18> (<class 'socket.error'>:[Errno 111] Connection refused [/usr/lib/python2.7/asyncore.py|read|83] [/usr/lib/python2.7/asyncore.py|handle_read_event|446] [/usr/lib/python2.7/asyncore.py|handle_connect_event|454])
Please advice
try:
a == b
except Exception as e:
print "error: %s"%(e)
Use this format.
I am programming a client-server instant message program. I created a similar program in Python 2, and am trying to program it in Python 3. The problem is when the server takes the message and tries to send it to the other client, it gives me "[Errno 32] Broken Pipe" and exits.
I have done some research, and found that this occurs when the client disconnects, so I did some more testing but could not find when the client disconnects. (I am using Ubuntu 14.04 and Python 3.4)
Here is the server code:
import socket, select, sys
def broadcast(sock, messaged):
for socket in connection_list:
if socket != s and socket != sock:
# Here is where it gives me the broken pipe error
try:
s.send(messaged.encode("utf-8"))
except BrokenPipeError as e:
print(e)
sys.exit()
connection_list = []
host = ''
port = 5558
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host,port))
s.listen(5)
connection_list.append(s)
read_sockets,write_sockets,error_sockets = select.select(connection_list,[],[])
while True:
for sock in read_sockets:
if sock == s:
conn, addr = s.accept()
connection_list.append(conn)
client = "Client (%s,%s) connected" % addr
print(client)
broadcast(sock,client)
else:
try:
data = sock.recv(2048)
decodeddata = data.decode("utf-8")
if data:
broadcast(sock, decodeddata)
except:
offline = "Client " + addr + "is offline"
broadcast(sock, offline)
print(offline)
connection_list.remove(sock)
sock.close()
continue
And the client code:
import socket, select, string, sys, time
def prompt(data) :
print("<You> " + data)
def Person(data) :
print("<Receiver> " + data)
if __name__ == "__main__":
host = "localhost"
port = 5558
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
try:
s.connect((host,port))
except:
print('Unable to connect')
sys.exit()
print('Connected.')
socket_list = [s]
read_sockets,write_sockets,error_sockets = select.select(socket_list,[],[])
while 1:
for sock in read_sockets:
if sock == s:
try:
time.sleep(1)
data = sock.recv(1024)
Person(data.decode("utf-8"))
except:
msg = input("Send a message: ")
try:
s.send(str.encode(msg))
except:
print("Server is offline")
sys.exit()
else:
print("Server is offline")
sys.exit()
There are two problems that you have to fix to make this work.
First, on both the client side and the server side, you have to put the select inside the loop, not outside. Otherwise, if there was something to read before you got to the loop, you'll recv over and over, and if there wasn't, you'll never recv. Once you fix this, you can get rid of the time.sleep(1). (You should never need a sleep to solve a problem like this; at best it masks the problem, and usually introduces new ones.)
Meanwhile, on the server side, inside broadcast, you're doing s.send. But s is your listener socket, not a connected client socket. You want socket.send here, because socket is each socket in connection_list.
There are a number of unrelated problems in your code as well. For example:
I'm not sure what the except: in the client is supposed to be catching. What it mainly seems to catch is that, about 50% of the time, hitting ^C to end the program triggers the send prompt. But of course, like any bare except:, it also masks any other problems with your code.
There's no way to send any data back and forth other than the "connected" message except for that except: clause.
addr is a tuple of host and port, so when someone goes offline, the server raises a TypeError from trying to format the offline message.
addr is always the last client who connected, not the one who's disconnecting.
You're not setting your sockets to nonblocking mode.
You're not checking for EOF on the recv. This means that you don't actually detect that a client has gone offline until you get an error. Which normally happens only after you try to send them a message (e.g., because someone else has connected or disconnected).
This question will expand on: Best way to open a socket in Python
When opening a socket how can I test to see if it has been established, and that it did not timeout, or generally fail.
Edit:
I tried this:
try:
s.connect((address, '80'))
except:
alert('failed' + address, 'down')
but the alert function is called even when that connection should have worked.
It seems that you catch not the exception you wanna catch out there :)
if the s is a socket.socket() object, then the right way to call .connect would be:
import socket
s = socket.socket()
address = '127.0.0.1'
port = 80 # port number is a number, not string
try:
s.connect((address, port))
# originally, it was
# except Exception, e:
# but this syntax is not supported anymore.
except Exception as e:
print("something's wrong with %s:%d. Exception is %s" % (address, port, e))
finally:
s.close()
Always try to see what kind of exception is what you're catching in a try-except loop.
You can check what types of exceptions in a socket module represent what kind of errors (timeout, unable to resolve address, etc) and make separate except statement for each one of them - this way you'll be able to react differently for different kind of problems.
You can use the function connect_ex. It doesn't throw an exception. Instead of that, returns a C style integer value (referred to as errno in C):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = s.connect_ex((host, port))
s.close()
if result:
print "problem with socket!"
else:
print "everything it's ok!"
You should really post:
The complete source code of your example
The actual result of it, not a summary
Here is my code, which works:
import socket, sys
def alert(msg):
print >>sys.stderr, msg
sys.exit(1)
(family, socktype, proto, garbage, address) = \
socket.getaddrinfo("::1", "http")[0] # Use only the first tuple
s = socket.socket(family, socktype, proto)
try:
s.connect(address)
except Exception, e:
alert("Something's wrong with %s. Exception type is %s" % (address, e))
When the server listens, I get nothing (this is normal), when it
doesn't, I get the expected message:
Something's wrong with ('::1', 80, 0, 0). Exception type is (111, 'Connection refused')
12 years later for anyone having similar problems.
try:
s.connect((address, '80'))
except:
alert('failed' + address, 'down')
doesn't work because the port '80' is a string. Your port needs to be int.
try:
s.connect((address, 80))
This should work.
Not sure why even the best answer didnt see this.