Python手动搭建http服务器

今天来用Python手动搭建http服务器

预备知识:

HTTP协议
Hypertext Transfer Protocol 超文本传输协议
协议的总用就是来传输超文本HTML(Hyper TextMarkupLanguage)

C/S架构 client-server
B/S架构 browser-server

http服务器的搭建

代码示例:

1
2
3
4
5
6
7
8
9
10
11
import socket
#服务器都是TCP协议
server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.bind(('10.0.42.248',9090))
server_socket.listen(128)
#获取到的数据是一个元组
#第0个元素是客户端的socket链接,第一个是客户端的IP地址和端口号
client_socket,client_addr = server_socket.accept()
#从客户端socket里获取数据
data = client_socket.recv(1024).decode('utf8')
print(data)

使用浏览器进行通信访问,发现由于没有设置响应头导致浏览器无法访问:

可以正常得到的返回数据是一个请求头:GET / HTTP/1.1

Host: 10.0.42.248:9090

Connection: keep-alive

Cache-Control: max-age=0

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.9

浏览器发送请求头服务器发送响应头,因此需要设置响应头:

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import socket
#服务器都是TCP协议
server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0',9090))
server_socket.listen(128)
#获取到的数据是一个元组
#第0个元素是客户端的socket链接,第一个是客户端的IP地址和端口号
client_socket,client_addr = server_socket.accept()
#从客户端socket里获取数据
data = client_socket.recv(1024).decode('utf8')
print(data)
#返回内容之前需要设置HTTP响应头
#HTTP/1.1 200 OK 是必须要写的项
#一行设置一个响应头,每行结束加上/n
client_socket.send('HTTP/1.1 200 OK\n'.encode('utf8'))
#所有的响应头设置完成之后再换行
client_socket.send('\n'.encode('utf8'))
#发送内容
client_socket.send('hello world'.encode('utf8'))

HTTP请求

1
2
3
4
5
6
7
8
9
#请求头
#GET /favicon.ico HTTP/1.1 #GET 请求方式,有GET/POST/PUT/DELETE... /表示请求路径
#Host: 10.0.42.248:9090 #请求的地址
#Connection: keep-alive
#User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36 #用户代理就像浏览器一样
#Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8
#Referer: http://10.0.42.248:9090/
#Accept-Encoding: gzip, deflate
#Accept-Language: zh-CN,zh;q=0.9

根据不同的请求响应不同的内容

附上代码:

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
import socket
#服务器都是TCP协议
server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0',9090))
server_socket.listen(128)
while True:
#获取到的数据是一个元组
#第0个元素是客户端的socket链接,第一个是客户端的IP地址和端口号
client_socket,client_addr = server_socket.accept()
#从客户端socket里获取数据
data = client_socket.recv(1024).decode('utf8')
print('接收到{}的访问数据:\n'.format(client_addr[0]))
#初始化请求头和响应头
response_head = 'HTTP/1.1 200 OK\n'
path = '/'
response_body = 'Hello World'
#在请求头内通过对字符串的处理方式可以得到不同的请求
first_line = (data.splitlines()[0])
path = first_line.split(' ')[1]

if path == '/login':
response_body = 'You Are In Login Surface'
elif path == '/register':
response_body = 'You Are In Register Surface'
elif path == '/' :
response_body = 'Your IP Is \n\n\n' + repr(client_addr[0])
else :
response_head = 'HTTP/1.1 404 Not Found\n'
response_body = '404 NOT FOUND'

#返回内容之前需要设置HTTP响应头
#HTTP/1.1 200 OK 是必须要写的项
#一行设置一个响应头,每行结束加上/n
#client_socket.send('HTTP/1.1 200 OK\n'.encode('utf8'))
#所有的响应头设置完成之后再换行
#client_socket.send('\n'.encode('utf8'))
response_head += 'content-type:text/html\n'
#如果需要输入中文可以增加请求头'charset:utf8\n'
response_head += '\n'
client_socket.send(response_head.encode('utf8'))

#发送内容,chrome浏览器默认编码是gbk
#因此如果需要输入中文可以默认编码为gbk或者在请求头添加'charset:utf8\n'
client_socket.send(response_body.encode('utf8'))
最后一步,就是面向对象的封装咯~;
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
import socket
class My_server(object):
def __init__(self,IP,port):
self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.IP = IP
self.port = port
self.socket.bind((IP,port))
self.socket.listen(128)
def run_server(self):
while True:
client_socket,client_addr = self.socket.accept()
data = client_socket.recv(1024).decode('utf8')
print('接收到{}的访问数据'.format(client_addr[0]))
response_head = 'HTTP/1.1 200 OK\n'
path = '/'
response_body = 'Hello World'
first_line = (data.splitlines()[0])
path = first_line.split(' ')[1]

if path == '/login':
response_body = 'You Are In Login Surface'
elif path == '/register':
response_body = 'You Are In Register Surface'
elif path == '/' :
response_body = 'Your IP Is \n\n\n' + repr(client_addr[0])
else :
response_head = 'HTTP/1.1 404 Not Found\n'
response_body = '404 NOT FOUND'

response_head += 'content-type:text/html\n'
response_head += '\n'

client_socket.send(response_head.encode('utf8'))
client_socket.send(response_body.encode('utf8'))
my_server = My_server('10.0.42.248',9090)
my_server.run_server()