最终版的Web(Python实现)
天啦,要考试了,要期末考试了,今天把最终版的Python搭建Web代码先写这里记下了。详细的过程先不写了。
这次是在前面的基础上重写 HTTPServer 与 BaseHTTPRequestHandler,主要利用 python 提供
的 socket 进行编程,从而实现消息的接收与相应;然后再接着引入多线程,分别处理来自客户
端的请求;最后实现根据客户端传递的参数动态生成页面的功能。
主要步骤如下:
一、 .重写 HTTPServer 与 BaseHTTPRequestHandler
Python socket 编程流程(服务器端) :
1. 第一步是创建 socket 对象。调用 socket 构造函数。如:
socket = socket.socket( family, type )
family 参数代表地址家族, 可为 AF_INET 或 AF_UNIX。 AF_INET 家族包括 Internet
地址,AF_UNIX 家族用于同一台机器上的进程间通信。
type 参数代表套接字类型,可为 SOCK_STREAM(流套接字)和 SOCK_DGRAM(数
据报套接字)。
2. 第二步是将socket绑定到指定地址。 这是通过socket对象的bind方法来实现的:
socket.bind( address )
由 AF_INET 所创建的套接字,address 地址必须是一个双元素元组,格式是
(host,port)。host 代表主机,port 代表端口号。如果端口号正在使用、主机名不正
确或端口已被保留,bind 方法将引发 socket.error 异常。
3. 第三步是使用 socket 套接字的 listen 方法接收连接请求。
socket.listen( backlog )
backlog 指定最多允许多少个客户连接到服务器。 它的值至少为 1。 收到连接请求后,
这些请求需要排队,如果队列满,就拒绝请求。
4. 第四步是服务器套接字通过 socket 的 accept 方法等待客户请求一个连接。
connection, address = socket.accept()
调 用 accept 方法时,socket 会时入“waiting”状态。客户请求连接时,方法建立连
接并返回服务器。 accept 方法返回一个含有两个元素的 元组(connection,address)。
第一个元素 connection 是新的 socket 对象,服务器必须通过它与客户通信;第二
个元素 address 是客户的 Internet 地址。
5. 第五步是处理阶段, 服务器和客户端通过 send 和 recv 方法通信(传输 数据)。 服
务器调用 send,并采用字符串形式向客户发送信息。send 方法返回已发送的字符
个数。服务器使用 recv 方法从客户接收信息。调用 recv 时,服务器必须指定一个
整数,它对应于可通过本次方法调用来接收的最大数据量。recv 方法在接收数据时
会进入“blocked”状态,最后返回一个字符 串,用它表示收到的数据。如果发送的数
据量超过了 recv 所允许的,数据会被截短。多余的数据将缓冲于接收端。以后调用
recv 时,多余的数据会从缓冲区 删除(以及自上次调用 recv 以来,客户可能发送的
其它任何数据)。
6. 传输结束,服务器调用 socket 的 close 方法关闭连接。
整个代码块儿如下:
注释有点乱, 中英文结合。。
Test.py
# -*-coding:utf-8 -*- import BaseHTTPServer import os import socket import subprocess import threading from datetime import datetime class ServerException( Exception ): pass # # 重写 HTTPServer 与 BaseHTTPRequestHandler,主要利用 python 提供 # 的 socket 进行编程,从而实现消息的接收与相应;然后再接着引入多线程,分别处理来自客户 # 端的请求;最后实现根据客户端传递的参数动态生成页面的功能。 # step1:reWrite HttpServer and BaseHTTPRequestHandler class HttpServer: def __init__(self, serverAddr, RequestHandler): self.serverAddr = serverAddr self.requestHandler = RequestHandler def serve_forever(self): # 1. create socket object(对象), call socket create function server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 1family=AF_INET,type=SOCK_STREAM server_sock.bind(self.serverAddr) # 2. call socket bind, aim to bind socket to pointed address # address must be a two-elements yuanzu, style is (host, port) # host stands for port number. if port number is in using\ #、host name is wrong or port number has been saved, bind way will # bring socket.error yi chang server_sock.listen(10) # 3. using socket's listen way to receive connect request # listen parament backlog=10:point allow no more than 10 clients # can connect to server. its value at least is 1. when received # request, those requests need pai dui,if list full, then refuse request while True: print 'waiting for connection...' clientsock, addr = server_sock.accept() # 4. server socket wait for client to request a connection # when call accept() function, socket will come into "wating" # states. when client request connection,function create # connection and return server.. # accept function return with two elements # (connection, address)., the first connection is new socket's # object, server must through it to tong xin with client. # the second element address is clients' Internet address print 'received from :', addr thread = threading.Thread(target=self.startThread, args=(clientsock, addr,)) thread.setDaemon(True) thread.start() # handler = RequestHandler(clientsock, addr,self) server_sock.close() def startThread(self, clientsock, addr): handler = RequestHandler(clientsock, addr, self) class HttpRequestHandler: bufsize = 1024 def __init__(self, clientsock, addr): self.cliensock = clientsock self.client_address = addr self.date_time_string = datetime.now() self.analyze() # http head part analyze def analyze(self): # receive dates, bufsize points to read dates num one time """ :type self: object """ data = self.cliensock.recv(self.bufsize) # print'receive ------->%s\n%s' %(datetime.now(), data) # chrome sometimes will send two request consist, tne second is null, reason is unknow if data.repalce(" ", "") == "": print "data is null" return data = data.split('\r\n') # first line is "GET/something.html?a=1&b=2 HTTP/1.1 firstLine = data[0] arr = firstLine.split(' ') self.command = arr[0] self.protocol = arr[2] if '?' in arr[1]: # path put absolute way self.path, self.paramStr = arr[1].spilt('?') else: self.path = arr[1] self.paramStr = None # put the remain of head information in heades's dictionary in the way of key value # Accept-Language : zh - cn # Connection : Keep - Alive # Host : Localhost # Accept - Encoding : gzip, deflate self.headers = {} for line in data[1:]: if ':' in line: key, value = line.split(':', 1) self.headers[key] = value # call function to deal with, this function has come in the first self.do_GET() # time.sleep(30) # when this function receive data, first feng li data # char string as th rule of '\r\n' # then ti qu first line, that is "GET/something.html?a=1&b=2 HTTP/1.1 # then analyze it , put it to the variable # path http_response = "HTTP/1.1" def send_response(self, status): if status == 200: self.http_response += "200" + " " + "OK" elif status == 404: self.http_response += "400" + " " + "Not Found" self.http_response += '\r\n' # "Content_Type", "text/html" # "Content-Length", Length def send_heade(self, key, value): self.http_response += str(key) + ": " + str(value) + '\r\n' def end_headers(self): self.http_response += '\r\n' def write(self, page): self.http_response += str(page) self.clientsock.send(self.http_response) self.cliensock.close() # those functions are pin zhuang http_response char string # as the rule of response head style class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): """dealt with and return page""" # page model Page = ''' <html> <body> <table border=2s> <tr> <td>Header</td> <td>Value</td> </tr> <tr> <td>Date</td><td> and time</td> <td>{date_time}</td> </tr> <tr> <td>Client host</td> <td>{client_host}</td> </tr> <tr> <td>Client port</td> <td>{client_port}</td> </tr> <tr> <td>Command</td> <td>{command}</td> </tr> <tr> <td>Path</td> <td>{path}</td> </tr> </table> </body> </html> ''' Error_Page = """\ <html> <body> <h1>Error accessing {path}</h1> <p>{msg}</p> </body> </html> """ def handle_error(self, msg): content = self.Error_Page.format( path=self.path, msg=msg ) self.send_content( content, 404 ) def handle_file(self, full_path): # 处理 python 脚本 if full_path.endswith('.py'): # data 为脚本运行后的返回值 data = subprocess.check_output(['python', full_path, self.paramStr] ) self.send_content(data) return try: with open(full_path, 'rb') as reader: content = reader.read() self.send_content(content) except IOError as msg: msg = "'{0}' cannot be read: {1}".format(self.path, msg ) self.handle_error(msg) # deal with a request def do_GET(self): # type: () -> object try: full_path = os.getcwd() + self.path if not os.path.exists(full_path): raise ServerException("'{0}' not found".format( self.path ) ) elif os.path.isfile(full_path): self.handle_file(full_path) # 访问根路径 elif os.path.isdir(full_path): # fullPath = os.path.join(fullPath, "index.html") full_path += "index.html" if os.path.isfile(full_path): self.handle_file(full_path ) else: raise ServerException( "'{0}' not found".format( self.path ) ) else: raise ServerException( "Unknown object '{0}'".format( self.path ) ) except Exception as msg: self.handle_error(msg) @property def create_page(self): values = { 'date_time': self.date_time_string( ), 'client_host': self.client_address[0], 'client_port': self.client_address[1], 'command': self.command, 'path': self.path } page = self.Page.format( **values ) return page pass def send_content(self, content, status=200): self.send_response(status) self.send_header("Content-type", "text/html" ) self.send_header("Content-Length", str( len( content ) ) ) self.end_headers() # self.wfile.write(self.create_page) self.wfile.write(content) # self.write(page) pass if __name__ == '__main__': serverAddr = ('localhost', 5555) server = HttpServer(serverAddr, RequestHandler ) server.serve_forever()
calc.py
import sys paramStr = sys.argv[1] paramArr = paramStr.split('&') paramDict = {} for param in paramArr: key, value = param.split('=') paramDict[key] = value print '''\ <html> <body> <p>a + b = {0}</p> </body> </html>'''.format((int(paramDict['a']) + int(paramDict['b'])))
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> <h1>Index Page </h1> <p>I love Python, to be honest</p> <table border=2s> <tr> <td>Header</td> <td>Value</td> </tr> <tr> <td>Date</td><td> and time</td> <td>{date_time}</td> </tr> <tr> <td>Client host</td> <td>{client_host}</td> </tr> <tr> <td>Client port</td> <td>{client_port}</td> </tr> <tr> <td>Command</td> <td>{command}</td> </tr> <tr> <td>Path</td> <td>{path}</td> </tr> </table> <p>please input first number:</p> <input> <br> <p>please input second number:</p> <input> <button>add</button> </body> </html>
运行效果如图:
好好准备期末考了。。。。
最终版的Web(Python实现)的更多相关文章
- python---session(最终版)__setitem__和__getitem__方法
一般来说对于其他语言session值一般获取方法为session['name'],赋值使用session['name']=val 对于python类中含有一些魔术方法__setitem__,__get ...
- Angular 2 最终版正式发布
9月15日,Angular 2 的最终版正式发布了. 作为 Angular 1 的全平台继任者 -- Angular 2 的最终版,意味着什么? 意味着稳定性已经得到了大范围用例的验证: 意味着已经针 ...
- 在sublimetext上打造一个兼容virtualenv的web&python开发环境
利用Sublimetext3&virtualenv 打造一个Web&Python IDE 注: 环境:window|python3;以下使用的sublimetext插件均用packag ...
- jQuery 3.0最终版发布,十大新特性眼前一亮
jQuery 3.0在日前发布了最终的全新版本.从2014年10月,jQuery团队对这个主要大版本进行维护开始,web开发者社区便一直在期待着这一刻的到来,终于在2016年6月他们迎来了这一个最终板 ...
- RHEL 6.0服务器安装Oracle 11G R2 最终版
RHEL6安装Oracle 11g R2最终版 结合网上教程 服务器实战所得 1.使用DVD做yum源新建dvd挂载目录[root@fxq-dp ~]# mkdir /media/iso进入到DVD挂 ...
- Windows版的各种Python库安装包下载地址与安装过程
在用Python开发时(Windows环境),会碰到需要安装某个版本的第三方库,为了以后查找.安装方便,总结如下: windows版的各种Python库安装包下载地址:http://www.lfd.u ...
- 理解JavaScript设计模式与开发应用中发布-订阅模式的最终版代码
最近拜读了曾探所著的<JavaScript设计模式与开发应用>一书,在读到发布-订阅模式一章时,作者不仅给出了基本模式的通用版本的发布-订阅模式的代码,最后还做出了扩展,给该模式增加了离线 ...
- PSPInstance Object | Web Python
PSPInstance Object | Web Python The PSPInstance object is available to all PSP pages through the psp ...
- HOWTO Use Python in the web — Python v3.0.1 documentation
HOWTO Use Python in the web - Python v3.0.1 documentation mod_python¶ People coming from PHP often f ...
随机推荐
- jdbc读取数据库,表相关信息(含注释)
读取数据库中的所有的表名 private Set<String> getTableNameByCon(Connection con) { Set<String> set = n ...
- asp.net gridview 分页显示不出来的问题
使用gridview分页显示,在点击第二页的时候显示空白,无数据. 原因是页面刷新,绑定datatable未执行 解决方法: 1.将datatable设置为静态 2.在OnPageIndexChang ...
- UVA1225
每增加1个整数,所有位上的对应数都加一.建立一个10000列10行的表,然后查表就可以了. #include<stdio.h> #include<string.h> ][]; ...
- Nginx配置性能优化
大多数的Nginx安装指南告诉你如下基础知识--通过apt-get安装,修改这里或那里的几行配置,好了,你已经有了一个Web服务器了.而且,在大多数情况下,一个常规安装的nginx对你的网站来说已经能 ...
- Linux sudo 命令的应用
.note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...
- JS-自制提速小工具:开发页面时需要按比例计算宽高值的快速计算器
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <meta name= ...
- JS原生ajax与Jquery插件ajax深入学习
序言: 近来随着项目的上线实施,稍微有点空闲,闲暇之时偶然发现之前写的关于javascript原生xmlHttpRequest ajax方法以及后来jquery插件ajax方法,于是就行了一些总结,因 ...
- js cookie
cookie:cookis:储存数据,当用户访问了某个网站的时候,我们就可以通过cookie来向访问者电脑上储存数据1)不同浏览器的存放cookie位置不一样,也是不能通用的2)cookie的存储是以 ...
- UP board 漫谈(1)——从Atom到UP Board
title: UP board 漫谈(1)--从Atom到UP Board date: 2016-12-26 12:33:03 tags: UP board categories: 开发板 perma ...
- ReportServices如何在一页中将报表分成两列显示
创建两个数据集 DataSet1 DataSet2 DataSet1 SELECT TOP (SELECT (COUNT(*) + 1) / 2 A ...