一个简易的HTTP网络服务器,基于tcp通信,将浏览器当作客户端,本地电脑当作服务器,按照HTTP网络协议返回格式内容,浏览器解析后产生界面。端口可自己设定,浏览器访问输入127.0.0.1:(自己设定的端口)(本地访问)或者自己的IP地址:(自己设定的端口),自己设定如果浏览器输入IP:端口/xxx.py,则视为请求的为动态内容。HTML文档自己可以在网上下一个模板,我也是随便下的一个,根据我的代码记得将其改为html文件存在可运行文件同一目录下,你也可以将其路径写成固定路径。html存html模板,package1为包,为浏览器请求为动态内容时,运行其中的文件。其思想运用到了面向对象使代码简化易改。
运行文件
import socket
import re
import multiprocessing
from package1 import mini_frame
import pymssql as sql
class WSGI_server(object):
def __init__(self):
# 1.创建套接字
self.tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 2.绑定本地信息
self.tcp_server_socket.bind(('',7788))
# 3.改为监听状态
self.tcp_server_socket.listen(128)
def server_client(self,new_socket):
'''返回客户端数据'''
# 1.接收请求
request = new_socket.recv(1024).decode('utf-8')
# print(request)
request_lines = request.splitlines()
print('')
print('>>'*10)
print(request_lines)
#匹配格式:GET /index.html HTTP/1.1
file_name = ''
ret = re.match('[^/]+(/[^ ]*)',request_lines[0])
if ret:
file_name = ret.group(1)
print('*'*10,file_name)
if file_name == '/':
file_name = '/index.html'
#返回HTTP格式数据给浏览器
if not file_name.endswith('.py'):
try:
f = open('./html' + file_name,"rb")
except:
#如果浏览器请求的内容无法打开,给浏览器回复信息
response = 'http/1.1 404 FILE NOT FOUND\r\n'
response += '\r\n'
response += 'File Not Found!'
new_socket.send(response.encode('utf-8'))
else:
html_content = f.read()
f.close()
# 2.发送数据(http格式)
response = 'http/1.1 200 ok\r\n' #\r\n 用来换行,不同与直接\n换行,\r\n是浏览器支持的换行格式
response += '\r\n'
#print(html_content)
#给浏览器发送header(头)
new_socket.send(response.encode('utf-8'))
#发给浏览器body(内容)
new_socket.send(html_content)
else:
envo = dict()
response_body = mini_frame.application(envo,self.start_response)
response_header = 'http/1.1 %s\r\n' %self.status
for temp in self.headers:
response_header += '%s:%s\r\n' %(temp[0],temp[1])
response_header += '\r\n'
response = response_header+response_body
new_socket.send(response.encode('utf-8'))
#关闭套接字
new_socket.close()
'''创建子进程时,子进程会复制父进程的资源,进程间不共享全局变量,线程间共享全局变量,
所以子进程调用new_socket ,需要重新关闭new_socket'''
def start_response(self,status,headers):
self.status = status #当前状态
self.headers = headers #头部信息
def run_server(self):
while True:
# 4.连接客户端,为客户端服务
new_socket, client_addr = self.tcp_server_socket.accept()
# 5.为客户服务
p = multiprocessing.Process(target = self.server_client, args=(new_socket,))
p.start()
new_socket.close()
# 创建子进程时,子进程会复制父进程的资源,进程间不共享全局变量,线程间共享全局变量
# 关闭套接字
self.tcp_server_socket.close()
def main():
web_server = WSGI_server()
web_server.run_server()
if __name__ == '__main__':
main()
要创建在同一目录下的包(package1)导入模块( mini_frame)
注:这个是我自己随便写的一个很low的动态模块,用于浏览器请求的动态内容返回的界面,我写的是一个查询本地SQL server中的表格内容返回给浏览器界面。这个模块可根据自己的想法,写个爬虫什么的都可以,这个模块可根据自己随意改。
import pymssql
import time
list1 = []
def sql():
# 1.链接数据库
conn = pymssql.connect(server = 'LAPTOP-QF6LJG98',user ='sa', password = '123456', database = 'ysl')
# 2.获取游标对象
cur = conn.cursor()
# 3.通过execute执行SQL语句,查询结果存在该游标中,通过fetchone,fetchmany(参数),fetchall分别取出一个,多个,全部查询结果
sql = 'select 价格 from JD_MAC;'
cur.execute(sql)
#cur.execute('select * from Name_Table')
rows = cur.fetchall()
conn.close()
for temp in rows:
list1.append(temp)
#print(temp)
return list1
#print(sql())
def application(envo,start_response):
start_response('200 OK',[('Content-Type','./html;')])
return 'The time is %s' %time.asctime()+str(sql())
动态界面没写好,返回的是一个 只有数据的表格,返回的是我爬取的MAC电脑的价格参数。表格前面是返回的当时时间。
静态请求(浏览器输入ip:端口或者ip:端口/index.html)斜杠后面可写可不写,因为默认为index.html,可参照代码看。
这是HTML模板的界面效果,这个模板很多,可在网上下载,不同模板界面不同 。
总结一下,代码很简单,主要了解一下原理,其中相关的WSGI框架自己还在学习,代码还在完善,浏览器电脑自带的ie浏览器就行,HTTP协议用的是1.1.