任务描述
本关任务:服务端读取客户端请求文件内容。
相关知识
为了完成本关任务,你需要掌握:
如何获取客户端请求的网页文件名
如何读取文件内容
如何获取客户端请求的网页文件名
HTTP 请求是客户端通过发送信息向服务器请求对资源的访问。HTTP 请求由三部分组成:请求行、请求头和请求正文。
下面是一个 HTTP 请求的数据:
POST /index.html HTTP/1.1 #请求方法 url 协议及版本号
Host: localhost #主机地址
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: <a target=_blank href="http://localhost/" style="color: rgb(51, 102, 153); text-decoration: none;">http://localhost/</a>
Content-Length:25
Content-Type:application/x-www-form-urlencoded
` `
username=aa&password=1234 #请求体
从上方代码可以看出,请求网页文件名位于请求行(第一行)中用空格分隔的第二个部分。
在 Python 中,可以使用字符串的 split() 函数来进行解析 HTTP 请求内容。
split():拆分字符串。通过指定分隔符对字符串进行切片,并返回分割后的字符串列表(list)。
#语法:
str.split(str="",num=string.count(str))[n]
'''
参数说明:
str:表示为分隔符,默认为空格,但是不能为空('')。若字符串中没有分隔符,则把整个字符串作为列表的一个元素
num:表示分割次数。如果存在参数num,则仅分隔成 num+1 个子字符串,并且每一个子字符串可以赋给新的变量
[n]:表示选取第n个分片
'''
示例:
str = "Line1-abcdef \nLine2-abc \nLine4-abcd";
print str.split( ); # 以空格为分隔符,包含 \n
print str.split(' ', 1 ); # 以空格为分隔符,分隔成两个
输出结果为:
['Line1-abcdef', 'Line2-abc', 'Line4-abcd']
['Line1-abcdef', '\nLine2-abc \nLine4-abcd']
结合上面 HTTP 请求格式可以看出,可以利用空格进行拆分,数组中的第 2 个元素即为请求文件名。
如何读取服务器上文件内容
在获得请求文件名后,读取文件内容使用文件操作来实现。
Python 提供了必要的函数和方法进行默认情况下的文件基本操作。你可以用 file 对象做大部分的文件操作。
open 方法
在具体的文件操作前你必须先用 Python 内置的 open() 函数打开一个文件,通过创建一个 file 对象,相关的方法才可以调用它进行读写。语法:
file object = open(file_name [, access_mode][, buffering])
close()方法
File 对象的 close() 方法刷新缓冲区里任何还没写入的信息,并关闭该文件,这之后便不能再进行写入。用 close() 方法关闭文件是一个很好的习惯。语法:
fileObject.close()
write()方法
write() 方法可将任何字符串写入一个打开的文件。Python 字符串可以是二进制数据,而不是仅仅是文字。语法:
fileObject.write(string)
参数 string 是要写入到已打开文件的内容。
read()方法
read() 方法从一个打开的文件中读取一个字符串。需要重点注意的是,Python 字符串可以是二进制数据,而不是仅仅是文字。语法:
fileObject.read([count])
参数 count 是要从已打开文件中读取的字节计数。该方法从文件的开头开始读入,如果没有传入 count,它会尝试尽可能多地读取更多的内容,很可能是直到文件的末尾。
读取文件内容示例:
# 打开一个文件
fo = open("foo.txt", "r+")
str = fo.read(10)
print "读取的字符串是 : ", str
# 关闭打开的文件
fo.close()
编程要求
根据提示,在右侧编辑器代码的 Begin-End 之间补充代码,读取 HTTP 请求的文件内容并打印出来。
测试说明
平台会向你的服务器程序发出浏览请求 helloworld.html 文件,对你编写的代码进行测试,并输出该文件内容:
预期输出:
开始WEB服务...
<head>hello world</head>
open error!!
答案:
#import socket module
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
#Prepare a sever socket
serverSocket.close()
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(("127.0.0.1",6789))
serverSocket.listen(1)
#while True:
print('开始WEB服务...')
try:
connectionSocket, addr = serverSocket.accept()
message = connectionSocket.recv(1024) # 获取客户发送的报文
#读取文件内容
######### Begin #########
fi = message.split()[1]
outputdata = open(fi[1:]).read()
######### End #########
print(outputdata)
connectionSocket.close()
except IOError:
connectionSocket.close()
serverSocket.close()