I'm trying to learn socket programming with python, and I've created a simple webserver, and I can connect to it in my browswer. I've opened an html file and send it, but it's not displaying in the browswer.
My simple webserver
import socket
import os
# Standard socket stuff:
host = ''
port = 8080
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(5)
# Loop forever, listening for requests:
while True:
csock, caddr = sock.accept()
print("Connection from: " + str(caddr))
req = csock.recv(1024) # get the request, 1kB max
print(req)
# Look in the first line of the request for a move command
# A move command should be e.g. 'http://server/move?a=90'
filename = 'static/index.html'
f = open(filename, 'r')
l = f.read(1024)
while (l):
csock.sendall(str.encode("""HTTP/1.0 200 OK\n""",'iso-8859-1'))
csock.sendall(str.encode('Content-Type: text/html\n', 'iso-8859-1'))
csock.send(str.encode('\n'))
csock.sendall(str.encode(""+l+"", 'iso-8859-1'))
print('Sent ', repr(l))
l = f.read(1024)
f.close()
csock.close()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>This is the body</p>
</body>
</html>
I'm very new at this, so I'm probably just missing a very minute details, but I'd love some help on getting the html file to correctly display in the browser.
I've tried your script works fine by the way.
Maybe you need to check the filename value.
note: little change to make sure all strings on html file sent.
import socket
import os
# Standard socket stuff:
host = ''
port = 8080
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(5)
# Loop forever, listening for requests:
while True:
csock, caddr = sock.accept()
print("Connection from: " + str(caddr))
req = csock.recv(1024) # get the request, 1kB max
print(req)
# Look in the first line of the request for a move command
# A move command should be e.g. 'http://server/move?a=90'
filename = 'static/index.html'
f = open(filename, 'r')
csock.sendall(str.encode("HTTP/1.0 200 OK\n",'iso-8859-1'))
csock.sendall(str.encode('Content-Type: text/html\n', 'iso-8859-1'))
csock.send(str.encode('\r\n'))
# send data per line
for l in f.readlines():
print('Sent ', repr(l))
csock.sendall(str.encode(""+l+"", 'iso-8859-1'))
l = f.read(1024)
f.close()
csock.close()
Result on browser
Related
I'm a beginner compsci student and I'm trying to code a simple server in python that takes a .HTML page stored in the same directory and sends it to a client on the same network using a TCP connection.
This is my code:
from socket import *
serverPort = 8000
serverSocket = socket(AF_INET, SOCK_STREAM)
# Prepare a sever socket
serverSocket.bind(('', serverPort)) # binds socket to port 8000
serverSocket.listen(1) # waiting for client to initiate connection
while True:
# Establish the connection
print('Ready to serve...')
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024)
filename = message.split()[1]
f = open(filename[1:].decode())
outputdata = f.read()
# Send one HTTP header line into socket
http_response = 'HTTP/1.1 200 OK\n'
connectionSocket.send(http_response.encode())
# 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()
except IOError:
connectionSocket.send("\r\n".encode())
# DO LATER
serverSocket.close()
sys.exit()
And this is my simple html page:
<!DOCTYPE html>
<html>
<body>
<h1>My First Web Page</h1>
<p>You have successfully accessed the Web Server</p>
</body>
</html>
So far whenever I run my server and direct my browser to it, I only get the following served to me:
<p>You have successfully accessed the Web Server</p>
Along with the body and html tags after this. Checking the page source there's no header.
I ran Wireshark while trying to access my server and indeed it seems like I'm only sending through "You have successfully accessed the Web server" and onwards. This is despite the fact a print function shows I am definitely sending all the data in the file through the TCP connection.
Does anyone know what the issue is?
After sending the protocol answer and headers, the actual response comes after two \r\n sequences.
Use this fixed code:
from socket import *
serverPort = 8000
serverSocket = socket(AF_INET, SOCK_STREAM)
# Prepare a sever socket
serverSocket.bind(('', serverPort)) # binds socket to port 8000
serverSocket.listen(1) # waiting for client to initiate connection
while True:
# Establish the connection
print('Ready to serve...')
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024)
filename = message.split()[1]
f = open(filename[1:].decode())
outputdata = f.read()
# Send one HTTP header line into socket
http_response = 'HTTP/1.1 200 OK\n'
connectionSocket.send(http_response.encode())
connectionSocket.send("\r\n".encode())
connectionSocket.send("\r\n".encode())
# Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i].encode())
connectionSocket.close()
except IOError:
# DO LATER
serverSocket.close()
sys.exit()
I would use the http.server library
import http.server
import socketserver
PORT = 8080
Handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
httpd.serve_forever()
source: https://www.afternerd.com/blog/python-http-server/
I'm just starting out with Python and I'm trying to code a simple web server. Everything seems to be work except I'm having one small problem. When I request a specific file like Test.html from my web server, the data in the HTML file is repeated over and over in my client like its stuck in a loop. So instead of seeing just "Test" displayed in the web client once, I see "Test Test Test Test Test Test...many times over". This is probably a simple error but I was hoping someone could point me in the right direction.
Thanks for you help!
import socket
import sys
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket Created!!")
try:
#bind the socket
#fill in start
server_address = ('localhost', 6789)
serversocket.bind(server_address)
#fill in end
except socket.error as msg:
print("Bind failed. Error Code: " + str(msg[0]) + "Message: " +
msg[1])
sys.exit()
print("Socket bind complete")
#start listening on the socket
#fill in start
serversocket.listen(1)
#fill in end
print('Socket now listening')
while True:
#Establish the connection
connectionSocket, addr = serversocket.accept()
print('source address:' + str(addr))
try:
#Receive message from the socket
message = connectionSocket.recv(1024)
print('message = ' + str(message))
#obtian the file name carried by the HTTP request message
filename = message.split()[1]
print('filename = ' + str(filename))
f = open(filename[1:], 'rb')
outputdata = f.read()
#Send the HTTP response header line to the socket
#fill in start
connectionSocket.send(bytes('HTTP/1.1 200 OK\r\n\r\n','UTF-
8'))
#fill in end
#Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata)
#close the connectionSocket
#fill in start
connectionSocket.close()
#fill in end
print("Connection closed!")
except IOError:
#Send response message for file not found
connectionSocket.send(bytes("HTTP/1.1 404 Not
Found\r\n\r\n","UTF-8"))
connectionSocket.send(bytes("<html><head></head><body><h1>404
Not Found</h1></body></html>\r\n","UTF-8"))
#Close the client socket
#fill in start
connectionSocket.close()
serverSocket.close()
You are stuck in a loop :)
#fill in end
#Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata)
You're sending the contents of outputdata the number of times however long the length of the file is.
You only need connectionSocket.send(outputdata) without the for..loop to send it once.
Also, make sure you close the file you read the contents from. (f.close())
I have a homework assignment which involves implementing a proxy cache server in Python for web pages. Here is my implementation of it
from socket import *
import sys
def main():
#Create a server socket, bind it to a port and start listening
tcpSerSock = socket(AF_INET, SOCK_STREAM) #Initializing socket
tcpSerSock.bind(("", 8030)) #Binding socket to port
tcpSerSock.listen(5) #Listening for page requests
while True:
#Start receiving data from the client
print 'Ready to serve...'
tcpCliSock, addr = tcpSerSock.accept()
print 'Received a connection from:', addr
message = tcpCliSock.recv(1024)
print message
#Extract the filename from the given message
filename = ""
try:
filename = message.split()[1].partition("/")[2].replace("/", "")
except:
continue
fileExist = False
try: #Check whether the file exists in the cache
f = open(filename, "r")
outputdata = f.readlines()
fileExist = True
#ProxyServer finds a cache hit and generates a response message
tcpCliSock.send("HTTP/1.0 200 OK\r\n")
tcpCliSock.send("Content-Type:text/html\r\n")
for data in outputdata:
tcpCliSock.send(data)
print 'Read from cache'
except IOError: #Error handling for file not found in cache
if fileExist == False:
c = socket(AF_INET, SOCK_STREAM) #Create a socket on the proxyserver
try:
srv = getaddrinfo(filename, 80)
c.connect((filename, 80)) #https://docs.python.org/2/library/socket.html
# Create a temporary file on this socket and ask port 80 for
# the file requested by the client
fileobj = c.makefile('r', 0)
fileobj.write("GET " + "http://" + filename + " HTTP/1.0\r\n")
# Read the response into buffer
buffr = fileobj.readlines()
# Create a new file in the cache for the requested file.
# Also send the response in the buffer to client socket and the
# corresponding file in the cache
tmpFile = open(filename,"wb")
for data in buffr:
tmpFile.write(data)
tcpCliSock.send(data)
except:
print "Illegal request"
else: #File not found
print "404: File Not Found"
tcpCliSock.close() #Close the client and the server sockets
main()
I configured my browsers to use my proxy server like so
But my problem when I run it is that no matter what web page I try to access it returns a 404 error with the initial connection and then a connection reset error with subsequent connections. I have no idea why so any help would be greatly appreciated, thanks!
There are quite a number of issues with your code.
Your URL parser is quite cumbersome. Instead of the line
filename = message.split()[1].partition("/")[2].replace("/", "")
I would use
import re
parsed_url = re.match(r'GET\s+http://(([^/]+)(.*))\sHTTP/1.*$', message)
local_path = parsed_url.group(3)
host_name = parsed_url.group(2)
filename = parsed_url.group(1)
If you catch an exception there, you should probably throw an error because it is a request your proxy doesn't understand (e.g. a POST).
When you assemble your request to the destination server, you then use
fileobj.write("GET {object} HTTP/1.0\n".format(object=local_path))
fileobj.write("Host: {host}\n\n".format(host=host_name))
You should also include some of the header lines from the original request because they can make a major difference to the returned content.
Furthermore, you currently cache the entire response with all header lines, so you should not add your own when serving from cache.
What you have doesn't work, anyway, because there is no guarantee that you will get a 200 and text/html content. You should check the response code and only cache if you did indeed get a 200.
a strange question.i can see about text_content. but i can't see pic_content,i don't know why. use chrome have a fault."Resource interpreted as Image but transferred with MIME type text/html:" and i discover maybe my if else codes does not work.pic must be image/jpg can output..but i don't know why and how to do ...
import socket
#Address
#httpq server
HOST = ''
PORT = 8000
#prepare HTTP response
#start line head and body
text_content = '''HTTP/1.x 200 OK
Content-Type: text/html
<html>
<head>
<title>WOW</titile>
</head>
<p>WOW,python server</p>
<img src="test.jpg/">
</html>
'''
#read picture ,put into HTTP format
f = open('test.jpg','rb')
pic_content = '''
HTTP/1.x 200 OK
Content-Type: image/jpg
'''
pic_content = pic_content + f.read()
f.close()
#cofigure socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((HOST,PORT))
#infinite loop,server forever
while True:
#3:maxinum number of requests waitting
s.listen(3)
conn, addr = s.accept()
request = conn.recv(1024)
method = request.split(' ')[0]
src = request.split(' ')[1]
#deal with GET method
if method =='GET':
#URL
if src =='/test.jpg':
content = pic_content
else:content = text_content
print 'Connected by',addr
print 'Request is:', request
conn.sendall(content)
#close connection
conn.close()
You are missing blank lines between the HTTP header and the body (after Content-Type).
Since you are already logging the request, you can see that the browser is requesting test.jpg/ with an extraneous trailing slash. Remove it, and it works.
I am trying to display text/html/css/images on my browser with a python web server.
But only the css/text/html is working. Anyone knows why the images are not showing?
Here is my code :
import urlparse
from socket import *
s = socket(AF_INET, SOCK_STREAM)
port = 8080
s.bind(('', port))
s.listen(1)
#Fill in end
while True:
client, addr = s.accept()
try:
data = client.recv(1024)
filename = data.split()[1]
file = open(filename[1:])
outputdata = file.read()
client.send('\nHTTP / 1.x200OK\n')
for i in range(0, len(outputdata)):
client.send(outputdata[i])
client.close()
except IOError:
client.send('\n404 File Not Found\n')
client.close()
s.close()
Thank you!
The problem is likely that you're not setting the right HTTP headers (Content-Type, Content-Length, etc). Instead of re-implementing this stuff from scratch, why not use one of the many Python web frameworks that will take care of all this for you?