用Python socket实现一个简单的http服务器(post 与get 的区别)


预备知识:

关于http协议的基础请参考这里。

关于socket基础函数请参考这里。

关于python网络编程基础请参考这里。


废话不多说,前面实现过使用linux c 或者python 充当客户端来获取http 响应,也利用muduo库实现过一个简易http服务器,现在来实现一个python版的简易http服务器,代码改编自http://www.cnblogs.com/vamei/


httpServer.py

Python Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/env python
#coding=utf-8

import socket
import re

HOST = ''
PORT = 8000

#Read index.html, put into HTTP response data
index_content = '''
HTTP/1.x 200 ok
Content-Type: text/html

'''

file = open('index.html', 'r')
index_content += file.read()
file.close()

#Read reg.html, put into HTTP response data
reg_content = '''
HTTP/1.x 200 ok
Content-Type: text/html

'''

file = open('reg.html', 'r')
reg_content += file.read()
file.close()

#Read picture, put into HTTP response data
file = open('http://www.2cto.com/uploadfile/2014/0528/20140528114249220.jpg', 'rb')
pic_content = '''
HTTP/1.x 200 ok
Content-Type: image/jpg

'''
pic_content += file.read()
file.close()



#Configure socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(100)

#infinite loop
while True:
# maximum number of requests waiting
conn, addr = sock.accept()
request = conn.recv(1024)
method = request.split(' ')[0]
src = request.split(' ')[1]

print 'Connect by: ', addr
print 'Request is:\n', request

#deal wiht GET method
if method == 'GET':
if src == '/index.html':
content = index_content
elif src == '/http://www.2cto.com/uploadfile/2014/0528/20140528114249220.jpg':
content = pic_content
elif src == '/reg.html':
content = reg_content
elif re.match('^/\?.*$', src):
entry = src.split('?')[1] # main content of the request
content = 'HTTP/1.x 200 ok\r\nContent-Type: text/html\r\n\r\n'
content += entry
content += '
register successs!

'
else:
continue


#deal with POST method
elif method == 'POST':
form = request.split('\r\n')
entry = form[-1] # main content of the request
content = 'HTTP/1.x 200 ok\r\nContent-Type: text/html\r\n\r\n'
content += entry
content += '
register successs!

'

######
# More operations, such as put the form into database
# ...
######

else:
continue

conn.sendall(content)

#close connection
conn.close()

chmod +x httpServer.py, 并运行./httpServer.py

使用浏览器当做客户端访问服务器

在httpServer.py 所在目录有index.html, reg.html, http://www.2cto.com/uploadfile/2014/0528/20140528114249220.jpg


1、访问目录: http://192.168.56.188:8000/index.html

服务器输出:

Connect by: ('192.168.56.1', 6274)
Request is:
GET /index.html HTTP/1.1
Host: 192.168.56.188:8000
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/33.0.1750.146 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4


回顾代码可知我们给客户端的响应是头部+index.html, index.html如下:

HTML Code
1
2
3
4
5
6
7
8
9
10


Jinan University



Python HTTP Server





进而进一步访问http://www.2cto.com/uploadfile/2014/0528/20140528114249220.jpg,由于我们在实现服务器时使用短连接,即响应一次就关掉连接,所以客户端会再发起一次连接,如下:

Connect by: ('192.168.56.1', 6275)
Request is:
GET /http://www.2cto.com/uploadfile/2014/0528/20140528114249220.jpg HTTP/1.1
Host: 192.168.56.188:8000
Connection: keep-alive
Accept: image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/33.0.1750.146 Safari/537.36
Referer: http://192.168.56.188:8000/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4


同样地,服务器响应头部+图片的二进制数据,如下图所示:

\

当然你也可以直接访问 http://192.168.56.188:8000/http://www.2cto.com/uploadfile/2014/0528/20140528114249220.jpg


<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+MqGit8POysS/wryjumh0dHA6Ly8xOTIuMTY4LjU2LjE4ODo4MDAwL3JlZy5odG1sPC9wPgo8cD63/s7xxvfK5LP2o7o8L3A+CjxwPkNvbm5lY3QgYnk6ICAo"192.168.56.1', 6282)
Request is:
GET /reg.html HTTP/1.1
Host: 192.168.56.188:8000
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/33.0.1750.146 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4


同样地,我们把头部+reg.html 响应过去,reg.html 是注册表单如下:

HTML Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65





register page








我们随便填一些信息上去然后点击提交数据,如下图:

\

此时浏览器会访问 http://192.168.56.188:8000/

服务器输出为:

Connect by: ("192.168.56.1', 6578)
Request is:
POST / HTTP/1.1
Host: 192.168.56.188:8000
Connection: keep-alive
Content-Length: 59
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://192.168.56.188:8000
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/33.0.1750.146 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://192.168.56.188:8000/reg.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4

user=simba&psw=1990&repsw=1990&sex=nan&tech=java&country=cn


注意:即表单中的name=value,以&分隔。


回顾代码,我们只是将浏览器提交的数据体直接发回去,再输出register success! 浏览器输出如下图:

\


如果我们把 表单中的

method 改成get,会是怎样的呢?


此时浏览器会访问 http://192.168.56.188:8000/?user=simba&psw=1990&repsw=1990&sex=nan&tech=java&country=cn


服务器输出为:

Connect by: ('192.168.56.1', 6382)
Request is:
GET /?user=simba&psw=1990&repsw=1990&sex=nan&tech=java&country=cn HTTP/1.1
Host: 192.168.56.188:8000
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/33.0.1750.146 Safari/537.36
Referer: http://192.168.56.188:8000/reg.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4


因为我们应答回去的数据跟post一致,故浏览器看到的输出也是一样的。


在这里可以总结一下post 跟 get 提交的一些区别:

get提交,提交的信息都显示在地址栏中;对于敏感数据不安全;由于地址栏存储体积有限而不能提交大容量数据;将信息封装到了请求消息的请求行

中,而post 提交将信息封装到了请求体中。



参考:

http://www.cnblogs.com/vamei/archive/2012/10/30/2744955.html

http://www.cnblogs.com/vamei/archive/2012/10/31/2747885.html


评论关闭