在本实验中,您将学习Python中TCP连接的套接字编程的基础知识:如何创建套接字,将其绑定到特定的地址和端口,以及发送和接收HTTP数据包。您还将学习一些HTTP首部格式的基础知识。

您将开发一个处理一个HTTP请求的Web服务器。您的Web服务器应该接受并解析HTTP请求,然后从服务器的文件系统获取所请求的文件,创建一个由响应文件组成的HTTP响应消息,前面是首部行,然后将响应直接发送给客户端。如果请求的文件不存在于服务器中,则服务器应该向客户端发送“404 Not Found”差错报文。

代码

在文件下面你会找到Web服务器的代码框架。您需要填写这个代码。而且需要在标有#Fill in start 和 # Fill in end的地方填写代码。另外,每个地方都可能需要不止一行代码。

运行服务器

将HTML文件(例如HelloWorld.html)放在服务器所在的目录中。运行服务器程序。确认运行服务器的主机的IP地址(例如128.238.251.26)。从另一个主机,打开浏览器并提供相应的URL。例如:
http://128.238.251.26:6789/HelloWorld.html

“HelloWorld.html”是您放在服务器目录中的文件。还要注意使用冒号后的端口号。您需要使用服务器代码中使用的端口号来替换此端口号。在上面的例子中,我们使用了端口号6789. 浏览器应该显示HelloWorld.html的内容。如果省略“:6789”,浏览器将使用默认端口80,只有当您的服务器正在端口80监听时,才会从服务器获取网页。

然后用客户端尝试获取服务器上不存在的文件。你应该会得到一个“404 Not Found”消息。

需要上交的内容

您需要上交完整的服务器代码,以及客户端浏览器的屏幕截图,用于验证您是否从服务器实际接收到HTML文件内容。

Web服务器的Python代码框架

  1. #import socket module
  2. from socket import *
  3. serverSocket = socket(AF_INET, SOCK_STREAM)
  4. #Prepare a sever socket
  5. #Fill in start
  6. #Fill in end
  7. while True:
  8. #Establish the connection
  9. print 'Ready to serve...'
  10. connectionSocket, addr = #Fill in start #Fill in end
  11. try:
  12. message = #Fill in start #Fill in end
  13. filename = message.split()[1]
  14. f = open(filename[1:])
  15. outputdata = #Fill in start #Fill in end
  16. #Send one HTTP header line into socket
  17. #Fill in start
  18. #Fill in end
  19. #Send the content of the requested file to the client
  20. for i in range(0, len(outputdata)):
  21. connectionSocket.send(outputdata[i])
  22. connectionSocket.close()
  23. except IOError:
  24. #Send response message for file not found
  25. #Fill in start
  26. #Fill in end
  27. #Close client socket
  28. #Fill in start
  29. #Fill in end
  30. serverSocket.close()

可选练习

  1. 目前,这个Web服务器一次只处理一个HTTP请求。请实现一个能够同时处理多个请求的多线程服务器。使用线程,首先创建一个主线程,在固定端口监听客户端请求。当从客户端收到TCP连接请求时,它将通过另一个端口建立TCP连接,并在另外的单独线程中为客户端请求提供服务。这样在每个请求/响应对的独立线程中将有一个独立的TCP连接。
  2. 不使用浏览器,编写自己的HTTP客户端来测试你的服务器。您的客户端将使用一个TCP连接用于连接到服务器,向服务器发送HTTP请求,并将服务器响应显示出来。您可以假定发送的HTTP请求将使用GET方法。 客户端应使用命令行参数指定服务器IP地址或主机名,服务器正在监听的端口,以及被请求对象在服务器上的路径。以下是运行客户端的输入命令格式。client.py server_host server_port filename

    答案

    作业1答案

    1. #改为Python3格式
    2. #import socket module
    3. from socket import *
    4. serverSocket = socket(AF_INET, SOCK_STREAM)
    5. #Prepare a sever socket
    6. serverPort = 80
    7. serverSocket.bind(("", serverPort))
    8. serverSocket.listen(1)
    9. while True:
    10. #Establish the connection
    11. print('Ready to serve...')
    12. connectionSocket, addr = serverSocket.accept()
    13. try:
    14. message = connectionSocket.recv(1024)
    15. filename = message.split()[1]
    16. f = open(filename[1:])
    17. outputdata = f.read()
    18. f.close()
    19. #Send one HTTP header line into socket
    20. outputdata = 'HTTP/1.1 200 OK\r\n\r\n' + outputdata
    21. #Send the content of the requested file to the client
    22. for i in range(0, len(outputdata)):
    23. connectionSocket.send(outputdata[i].encode())
    24. connectionSocket.close()
    25. print("OK!")
    26. except IOError:
    27. #Send response message for file not found
    28. outputdata = 'HTTP/1.1 404 Not Found\r\n\r\n'
    29. #Close client socket
    30. for i in range(0, len(outputdata)):
    31. connectionSocket.send(outputdata[i].encode())
    32. connectionSocket.close()
    33. serverSocket.close()

    可选练习1答案

    ```python

    改为Python3格式

    import socket module

    from socket import * import threading def webProcess(connectionSocket): try:
    1. message = connectionSocket.recv(1024)
    2. filename = message.split()[1]
    3. f = open(filename[1:], "rb")
    4. outputdata = f.read()
    5. outputdata = outputdata.decode()
    6. f.close()
    7. #Send one HTTP header line into socket
    8. outputdata = 'HTTP/1.1 200 OK\r\n\r\n' + outputdata
    9. #Send the content of the requested file to the client
    10. for i in range(0, len(outputdata)):
    11. connectionSocket.send(outputdata[i].encode())
    12. connectionSocket.close()
    13. print("OK!")
    except IOError:
    1. #Send response message for file not found
    2. outputdata = 'HTTP/1.1 404 Not Found\r\n\r\n'
    3. #Close client socket
    4. for i in range(0, len(outputdata)):
    5. connectionSocket.send(outputdata[i].encode())
    6. connectionSocket.close()

serverSocket = socket(AF_INET, SOCK_STREAM)

Prepare a sever socket

serverPort = 80 serverSocket.bind((“”, serverPort)) serverSocket.listen(10)

while True:

  1. #Establish the connection
  2. print('Ready to serve...')
  3. connectionSocket, addr = serverSocket.accept()
  4. thread = threading.Thread(target = webProcess, args = (connectionSocket, ))
  5. thread.start()

serverSocket.close()

  1. <a name="v5oLO"></a>
  2. ## 可选练习2答案
  3. ```python
  4. #Python3格式
  5. from socket import *
  6. serverName = '127.0.0.1'
  7. serverPort = 80
  8. clientSocket = socket(AF_INET, SOCK_STREAM)
  9. clientSocket.connect((serverName, serverPort))
  10. outputdata = 'GET /hello.html HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n'
  11. clientSocket.send(outputdata.encode())
  12. data = 1
  13. while data:
  14. data = clientSocket.recv(1024)
  15. print(data.decode(), end = '')
  16. clientSocket.close()