Python Socket Programming - Bad file descriptor error - python

I'm trying to create a simple server, and keep getting the following error in IDLE:
File "C:\Python27\lib\socket.py", line 202, in accept
sock, addr = self._sock.accept()
File "C:\Python27\lib\socket.py", line 170, in _dummy
raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor
This is my code. I've tried understanding why, and it has something to do with closing one of the sockets and then trying to use it again but I don't really get how I'm supposed to fix it. Any and all help is appreciated. :)
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
port=10101
serverSocket.bind(('',port))
serverSocket.listen(5)
while True:
print 'Ready to serve...'
connectionSocket, addr = serverSocket.accept()
try:
message = serverSocket.recv(1024)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
connectionSocket.send("HTTP/1.1 200 OK\r\n\n")
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i])
connectionSocket.close()
except IOError:
connectionSocket.send('HTTP/1.1 404 File not found\r\n\n')
connectionSocket.close()
serverSocket.close()
serverSocket.close()

A couple of things:
As user27994550 put in his code, you want to use
message = connectionSocket.recv(1024)
to receive messages, not the server socket.
The other thing that both of your codes missed is you don't want to call
serverSocket.close()
in your except function unless you're closing the program overall. If you close the server socket, the next time you call
connectionSocket, addr = serverSocket.accept()
you won't be able to accept another connection. Hope this helps!

You are trying to use the "message" variable data without checking if its empty.
I think this might be the problem.
Try this:
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
port=10101
serverSocket.bind(('localhost',port))
serverSocket.listen(5)
while True:
print('Ready to server')
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024)
if message != "": #Checking if empty
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
connectionSocket.send("HTTP/1.1 200 OK\r\n\n")
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i])
connectionSocket.close()
except IOError:
connectionSocket.send('HTTP/1.1 404 File not found\r\n\n')
connectionSocket.close()
serverSocket.close()

Related

Python Error ConnectionAbortedError: [WinError 10053]

I am experimenting with import sockets in python and I have a client.py and a server.py and when server.py receives a message from client.py I get this error
Traceback (most recent call last):
File "C:/Users/Owner/PycharmProjects/pythonProject/echo_server.py", line 13, in <module>
data = conn.recv(1024)
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine
My full code is:
import socket
host = ''
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print(host , port)
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
data = str(data)
if not data: break
print("Client Says: "+data)
conn.sendall(b"Server Says:Message Received")
input(">")
conn.close()
Can someone tell me what this error is and what I can do to fix it?
The if statement if not data is equivalent to writing if data != "", while the empty string your server receives is b''. You have several options to fix it.
data = conn.recv(1024).decode() is the proper way to allocate the data sent by the client. You can now print(data) or compare data to an empty string.
If you still don't want to decode() your message you could change your if statement to if data != b'' or if data is not None.
Update
If it wasn't clear, your str(data) conversion causes the if statement to work unproperly, which is set to False without allowing you to break when a client disconnects.

Trying to use a Pycharm generated socket to pull the contents of an HTML file in the same directory

So essentially, I have an HTML file in the same directory as my .py file, which contains the following code:
import sys
from socket import *
serverPort = 12500
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
while True:
print('The server is ready to receive')
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024).decode()
filename = message.split()[1]
print(filename)
temp = open(filename[1:])
outputdata = temp.readlines()
print(outputdata)
connectionSocket.send(bytes('HTTP/1.1 200 OK\r\n\r\n', encoding='UTF-8'))
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i].encode())
connectionSocket.send("\r\n".encode())
connectionSocket.close()
except IOError:
connectionSocket.send(bytes('HTTP/1.1 404 NOT FOUND\r\n\r\n', encoding="UTF-8"))
connectionSocket.close()
serverSocket.close()
sys.exit()
My goal for this server is that it displays the content of the HTML file when I reference it in a web browser, and gives a 404 error when a non-existent file is found.
An example input would be:
http://127.0.0.1:12500/Hello.html
This would yield this output with my current code:
The server is ready to receive
/Hello.html
So it is just reading the /Hello.html portion instead of the file. Is there a way to remedy this? Thank you!

List index out of range preventing 404 error?

I'm trying to complete this lab but cannot seem to get it to work correctly. When I try to get a file not present of the server, I am given
This page isn’t working
127.0.0.1 sent an invalid response.
ERR_INVALID_HTTP_RESPONSE
The response I'd like to get is along the lines of
404 File not found
When I try to load a file not present, the compiler says for line 16:
filename = message.split()[1]
IndexError: list index out of range
The code compiles and I am able to open my Hello World file, but I am just not able to get this 404 error. I was given a skeleton code, so there are some things that I cannot change without deviating from course material.
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
#Prepare a server socket
serverPort = 7000
serverSocket.bind(('127.0.0.1', serverPort))
serverSocket.listen(5)
while True:
print('Ready to serve...')
connectionSocket, addr = serverSocket.accept()
#Fill in start #Fill in end
try:
message = connectionSocket.recv(1024)
print (message)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
#Send one HTTP header line into socket
#Fill in start
connectionSocket.send('\nHTTP/1.x 200 OK\n'.encode())
#Fill in end
#Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i].encode())
connectionSocket.send("\r\n".encode())
connectionSocket.close()
print ('File Recieved')
except IOError:
connectionSocket.send('\n404 File Not Found\n'.encode())
connectionSocket.close()
#Close client socket
serverSocket.close()
sys.exit()
The skeleton code appears to be Python 2, and I'm using Python 3. I've made some minor syntax adjustments to adjust.
Removing print(message) yields "File Recieved" in the compiler, but still no 404 error in the browser. I'm at loss after 8 hours.
One way to handle an IndexError in message.split()[1] is to handle and IndexError in message.split()[1] ;)
try:
filename = message.split()[1]
except IndexError:
send_404_response()
continue

Python web server - IndexError when splitting filename

I have successfully been able to access my web-server from a browser, downloaded a file on the server and properly viewed it with chrome. However, when the server standbys for approx. 20 seconds, it'll crash with an IndexError.
from socket import *
serverport = 972
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverport))
serverSocket.listen(1)
print 'Standing by...'
while True:
#Establish the connection
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i])
print 'Success! File sent!'
connectionSocket.close()
except IOError:
errormessage = 'Error 404 - File not found'
connectionSocket.send(errormessage)
The output i get is the following:
Standing by..
Success! File sent! #sent everytime i request the webpage on the client localhost:80/helloworld.html
Traceback (most recent call last):
File "C:/Users/Nikolai/Dropbox/NTNU/KTN/WebServer/TCPServer.py", line 14, in <module>
filename = message.split()[1]
IndexError: list index out of range
This is probably the client closing the connection. When the connection is finished, an empty string '' is received.
''.split()[1] will fail with index out of range. My advice is to try with this patch:
message = connectionSocket.recv(1024)
if not message:
# do something like return o continue
As an aside, you should recv from your socket until you get the empty string. In your code, what happens if the request is larger than 1024? Something like this can be done:
try:
message = ''
rec = connectionSocket.recv(1024)
while rec:
rec = connectionSocket.recv(1024)
message += rec
if not message:
connectionSocket.close()
continue
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i])
print 'Success! File sent!'
connectionSocket.close()
You should read Socket Programming HOWTO, specially the part of creating multithreaded servers, which is probably how you want to do yours :)
Hope this helps!

error when trying to connect to server for next the connection using sockets in python

I am learning socket programming using python. my first assignment is to a write a client.py and a server.py. The client sends a message to server. The server receives the message of 16 bytes each time. After it has received the entire message, it will send the same message back to client.
so it is very simple. The server has backlog of 1. After the server sends the message to client, the connection to client close and the server should be open to receive new connection.
my current code fails in the last step. It is not open to receive new connections. It is throwing error. I even figured out the error. but I do not know how to fix this.
The error comes from server.py because I call for sock.accept() but I have closed the sock.
Let me explain my server.py code: I have two while loops. The outer loop looks for new connection, and the inner loop looks process request from connections i.e it simply receives data, wait till everything is received and send it back to client and finally close the connection.
I am asked not to change the structure of two while loops but just implement them.
Any thoughts or ideas on this:
client.py
import socket
import sys
def client(msg, log_buffer=sys.stderr):
server_address = ('localhost', 10000)
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP)
sock.connect(server_address)
print >>log_buffer, 'connecting to {0} port {1}'.format(*server_address)
try:
print >>log_buffer, 'sending "{0}"'.format(msg)
sock.sendall(msg)
chunk = ''
done=False;
while not done:
chunk+=sock.recv(16)
if chunk==msg:
done=True
print >>log_buffer, 'received "{0}"'.format(chunk)
finally:
print >>log_buffer, 'closing socket'
sock.close()
if __name__ == '__main__':
if len(sys.argv) != 2:
usg = '\nusage: python echo_client.py "this is my message"\n'
print >>sys.stderr, usg
sys.exit(1)
msg = sys.argv[1]
client(msg)
Server.py
import socket
import sys
def server(log_buffer=sys.stderr):
# set an address for our server
address = ('127.0.0.1', 10000)
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# log that we are building a server
print >>log_buffer, "making a server on {0}:{1}".format(*address)
sock.bind(address)
sock.listen(1)
try:
# the outer loop controls the creation of new connection sockets. The
# server will handle each incoming connection one at a time.
while True:
print >>log_buffer, 'waiting for a connection'
conn,add=sock.accept()
addr=(conn,add)
try:
print >>log_buffer, 'connection - {0}:{1}'.format(*addr)
# the inner loop will receive messages sent by the client in
# buffers. When a complete message has been received, the
# loop will exit
data = ''
while True:
recvdata=conn.recv(16)
print recvdata
data+=recvdata
print >>log_buffer, 'received "{0}"'.format(data)
print >>log_buffer, "len of received data: {0}".format(len(recvdata))
if len(recvdata)<16:
print >>log_buffer,"sending data"
conn.sendall(data)
break
conn.close()
finally:
sock.close()
except KeyboardInterrupt:
sock.close()
if __name__ == '__main__':
server()
sys.exit(0)
I runpython server.py in one terminal andpython client.py "This is the first message. send me back"` in a different terminal. The client connection is lost normally as expected. But I get the following error at server side (towards the end):
making a server on 127.0.0.1:10000
waiting for a connection
connection - <socket._socketobject object at 0x100849c20>:('127.0.0.1', 50626)
sairam hopefully
received "sairam hopefully"
len of received data: 16
this works lets
received "sairam hopefully this works lets"
len of received data: 16
c
received "sairam hopefully this works lets c"
len of received data: 2
sending data
waiting for a connection
Traceback (most recent call last):
File "echo_server.py", line 89, in <module>
server()
File "echo_server.py", line 39, in server
conn,add=sock.accept()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 202, in accept
sock, addr = self._sock.accept()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 170, in _dummy
raise error(EBADF, 'Bad file descriptor')
socket.error: [Errno 9] Bad file descriptor
You are closing sock inside your while loop. Don't do that. sock is your long-lasting server socket, which needs to remain open to listen for new connections. conn is your ephemeral socket, which needs to remain open only the length of a single connection.
Close conn after each connection, close sock when the server needs to terminate.
More simply, replace these lines:
finally:
sock.close()
with
finally:
conn.close()
What you are trying to do is a simple echo server, which I believe you can implement much more simply.
Server:
import socket
host = ''
port = 50000
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
data = client.recv(size)
if data:
client.send(data)
client.close()
Client:
import socket
host = 'localhost'
port = 50000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.send('Hello, world')
data = s.recv(size)
s.close()
print 'Received:', data

Categories