Search code examples
pythonhtmltcp

Issue with writing simple TCP server in python


I am writing a is simple TCP server using python. when i type in "localhost:12001/HelloWorld.html" into my web browser it is meant to display "Hello world" from the html file saved in my directory.

When i run it, this is what is displayed in my web browser:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta http-equiv="Content-Style-Type" content="text/css">
  <title></title>
  <meta name="Generator" content="Cocoa HTML Writer">
  <meta name="CocoaVersion" content="2113.5">
  <style type="text/css">
    p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px 'Helvetica Neue'; color: #000000; -webkit-text-stroke: #000000}
    span.s1 {font-kerning: none}
  </style>
</head>
<body>
<p class="p1"><span class="s1">Hello World !</span></p>
</body>
</html>

Here is my source code :

from socket import *

serverSocket = socket(AF_INET, SOCK_STREAM) 
serverPort = 12001
serverSocket.bind(('127.0.0.1', serverPort))
serverSocket.listen(1)

while True:

    print('Ready to serve...')
    connectionSocket, addr = serverSocket.accept()

    try:

        message = connectionSocket.recv(1024).decode()
        filename = message.split()[1]
        f = open(filename[1:])
        outputdata = f.read()
     
# #Send one HTTP header line into socket
        connectionSocket.send('HTTP/1.1 200 OK\r\n\r\n')
        
#Send the content of the requested file to the client
        for i in range(0, len(outputdata)):
            connectionSocket.send(outputdata[i])
        connectionSocket.close()
    except IOError:
    #Send response message for file not found
        print('404 Not Found')
        connectionSocket.send("""HTTP/1.0 404 Not Found\r\n""".encode());

#Close client socket
        connectionSocket.close()

any help is appreciated , thanks


Solution

    1. Don't send your text one character at a time in a loop

    Change this:

    for i in range(0, len(outputdata)):
        connectionSocket.send(outputdata[i])
    

    To this:

    connectionSocket.send(outputdata)
    
    1. Encode all response strings as utf-8 bytes
    outputdata = f.read().encode(encoding='utf-8')
    
    1. Add the Content-Length and Content-Type headers to response

    So browser will know how to use this

    connectionSocket.send('HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n'
                          .format(outputlength)
                          .encode(encoding='utf-8'))
    

    Content-Length is a length of your data in bytes (outputdata)

    Content-Type tells the browser how to interpret the response (text/html)

    My working example of your code:

    from socket import *
    
    serverSocket = socket(AF_INET, SOCK_STREAM)
    serverPort = 12001
    serverSocket.bind(('127.0.0.1', serverPort))
    serverSocket.listen(1)
    
    while True:
        print('Ready to serve...')
        connectionSocket, addr = serverSocket.accept()
        
        try:
            message = connectionSocket.recv(1024).decode()
            filename = message.split()[1]
            f = open(filename[1:])
            outputdata = f.read().encode(encoding='utf-8')
            outputlength = len(outputdata)
            
            # #Send one HTTP header line into socket
            connectionSocket.send('HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n'
                                  .format(outputlength)
                                  .encode(encoding='utf-8'))
            
            # Send the content of the requested file to the client
            connectionSocket.send(outputdata)
            connectionSocket.close()
        except IOError:
            # Send response message for file not found
            print('404 Not Found')
            connectionSocket.send("""HTTP/1.0 404 Not Found\r\n""".encode())
            
            # Close client socket
            connectionSocket.close()