http协议
一、http简介
1.HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
2.HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展
3.HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。
二、http协议的特点
1、简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。
由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
2、灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
3.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
4.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。
缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
三、http请求协议
1、http请求协议遵循以下格式
请求协议遵循以下格式:
请求首行; //请求方式、请求路径、协议和版本 如:GET /index.html http/127.0.0.1
请求头信息; 请求头名称:请求头内容,即key:value格式
空行 : 用来用请求体分开
请求体: GET 没有请求体,POST有请求体
在http协议中最为常用的请求体是GET,与POST
2.get的请求
GET /562f25980001b1b106000338.jpg HTTP/1.1Host img.mukewang.comUser-Agent Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36Accept image/webp,image/*,*/*;q=0.8Referer http://www.imooc.com/Accept-Encoding gzip, deflate, sdchAccept-Language zh-CN,zh;q=0.8
HTTP默认的请求方法就是GET
* 没有请求体 * 数据量有限制! * GET请求数据会暴露在浏览器的地址栏中GET请求常用的操作:
1. 在浏览器的地址栏中直接给出URL,那么就一定是GET请求 2. 点击页面上的超链接也一定是GET请求 3. 提交表单时,表单默认使用GET请求,但可以设置为POST请求头
1、Host请求的web服务器域名地址2、User-AgentHTTP客户端运行的浏览器类型的详细信息。通过该头部信息,web服务器可以判断出http请求的客户端的浏览器的类型。3、Accept指定客户端能够接收的内容类型,内容类型的先后次序表示客户都接收的先后次序4、Accept-Lanuage指定HTTP客户端浏览器用来展示返回信息优先选择的语言5、Accept-Encoding指定客户端浏览器可以支持的web服务器返回内容压缩编码类型。表示允许服务器在将输出内容发送到客户端以前进行压缩,以节约带宽。而这里设置的就是客户端浏览器所能够支持的返回压缩格式。6、Accept-CharsetHTTP客户端浏览器可以接受的字符编码集7、Content-Type显示此HTTP请求提交的内容类型。一般只有post提交时才需要设置该属性有关Content-Type属性值有如下两种编码类型:(1)“application/x-www-form-urlencoded”: 表单数据向服务器提交时所采用的编码类型,默认的缺省值就是“application/x-www-form-urlencoded”。 然而,在向服务器发送大量的文本、包含非ASCII字符的文本或二进制数据时这种编码方式效率很低。(2)“multipart/form-data”: 在文件上载时,所使用的编码类型应当是“multipart/form-data”,它既可以发送文本数据,也支持二进制数据上载。当提交为表单数据时,可以使用“application/x-www-form-urlencoded”;当提交的是文件时,就需要使用“multipart/form-data”编码类型。
3.post请求
POST / HTTP1.1Host:www.wrox.comUser-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)Content-Type:application/x-www-form-urlencodedContent-Length:40Connection: Keep-Alivename=Professional%20Ajax&publisher=Wiley
http响应协议
三、响应格式
1.HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
复制代码HTTP/1.1 200 OKDate: Fri, 22 May 2009 06:07:21 GMTContent-Type: text/html; charset=UTF-8
第一部分:状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。
第一行为状态行,(HTTP/1.1)表明HTTP版本为1.1版本,状态码为200,状态消息为(ok)
第二部分:消息报头,用来说明客户端要使用的一些附加信息
第二行和第三行为消息报头,
Date:生成响应的日期和时间;Content-Type:指定了MIME类型的HTML(text/html),编码类型是UTF-8第三部分:空行,消息报头后面的空行是必须的
第四部分:响应正文,服务器返回给客户端的文本信息。
空行后面的html部分为响应正文。
2.响应状态吗
状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:1xx:指示信息--表示请求已接收,继续处理2xx:成功--表示请求已被成功接收、理解、接受3xx:重定向--要完成请求必须进行更进一步的操作4xx:客户端错误--请求有语法错误或请求无法实现5xx:服务器端错误--服务器未能实现合法的请求常见状态码:200 OK //客户端请求成功400 Bad Request //客户端请求有语法错误,不能被服务器所理解401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 403 Forbidden //服务器收到请求,但是拒绝提供服务404 Not Found //请求资源不存在,eg:输入了错误的URL500 Internal Server Error //服务器发生不可预期的错误503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常复制代码
四、get与post请求区别
GET请求GET /books/?sex=man&name=Professional HTTP/1.1Host: www.wrox.comUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)Gecko/20050225 Firefox/1.0.1Connection: Keep-Alive注意最后一行是空行POST请求POST / HTTP/1.1Host: www.wrox.comUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)Gecko/20050225 Firefox/1.0.1Content-Type: application/x-www-form-urlencodedContent-Length: 40Connection: Keep-Alivename=Professional%20Ajax&publisher=Wiley
1、 在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放在HTTP包的body中。
2、 GET方式提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST则没有此限制。
3、安全性问题。正如在(1)中提到,使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。
4.、服务器取值方式不一样。GET方式取值,如php可以使用$_GET来取得变量的值,而POST方式通过$_POST来获取变量的值。
web应用与web框架
对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。
import socketdef handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8")) client.send("Hello, yuan
".encode("utf8"))def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8001)) sock.listen(5) while True: connection, address = sock.accept() handle_request(connection) connection.close()if __name__ == '__main__': main()
wsgiref模块
from wsgiref.simple_server import make_serverdef application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'Hello, web!
']httpd = make_server('', 8080, application)print('Serving HTTP on port 8000...')# 开始监听HTTP请求:httpd.serve_forever()
创建一个自己的框架
manage.py
import wsgiprint("server is working...")wsgi.s.serve_forever()
urls
from app01 import views# 路径与逻辑函数的映射关系URLpattern= ( ("/login", views.login), ("/auth", views.auth), ("/reg", views.reg), ("/reg_auth", views.reg_auth))
views
def login(environ): with open("template/login.html", "rb") as f: data = f.read() return datadef auth(environ): print("QUERY_STRING", environ.get("QUERY_STRING")) # user=yuan&pwd=123 useron, pwdon = environ.get("QUERY_STRING").split("&") _, user = useron.split("=") _, pwd = pwdon.split("=") import pymysql # 连接数据库 # conn = pymysql.connect(host='', port=3306, user='root', passwd='', db='s6') # db:库名 conn = pymysql.connect(host='localhost', user='root', password='123', database='s6') # 创建游标 cur = conn.cursor() SQL = "select * from userinfo WHERE NAME ='%s' AND PASSWORD='%s'" % (user, pwd) cur.execute(SQL) if cur.fetchone(): with open("template/backend.html", "r") as f: data = f.read() data = data % user return data.encode("utf8") else: with open("template/login.html", "rb") as f: data = f.read() return datadef reg(environ): with open("template/reg.html", "rb") as f: data = f.read() return datadef reg_auth(environ): print("QUERY_STRING", environ.get("QUERY_STRING")) useron, pwdon ,repeat_pwdon= environ.get("QUERY_STRING").split("&") _,user= useron.split("=") _,pwd = pwdon.split("=") _,repeat_pwd = repeat_pwdon.split("=") print(user,pwd,repeat_pwd) if repeat_pwd==pwd: import pymysql conn = pymysql.connect(host='localhost', user='root', password='123', database='s7') cur = conn.cursor() SQL="insert into userinfo1(name,password) values('%s','%s')"%(user,pwd) cur.execute(SQL) conn.commit() with open("template/login.html","rb") as f: data = f.read() return data else: with open("template/reg.html","rb") as f: data = f.read() return data
models
import pymysql#连接数据库# conn = pymysql.connect(host='localhost',port= 3306,user = 'root',password='123',db='s6') #db:库名conn=pymysql.connect(host='localhost',user='root',password='123',database='s7')#创建游标cur = conn.cursor()# sql='''# create table userinfo(# id INT PRIMARY KEY ,# name VARCHAR(32) ,# password VARCHAR(32)# )## # '''sql='''create table userinfo1( id INT PRIMARY KEY auto_increment, name VARCHAR(32) , password VARCHAR(32))'''cur.execute(sql)# cur.executemany("insert into userinfo values(%s,%s,%s)", [(1,"yuan","123"),# (2,"alex","456"),# (3,"egon","789")])cur.executemany("insert into userinfo1 values(%s,%s,%s)", [(1,"yuan","123"), (2,"alex","456"), (3,"egon","789")])conn.commit()#关闭指针对象cur.close()#关闭连接对象conn.close()
wsgi
from wsgiref.simple_server import make_serverimport urlsdef application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) print("environ",environ) print("path",environ.get("PATH_INFO")) # /login path=environ.get("PATH_INFO") # /auth URLpattern=urls.URLpattern print("URLpattern",URLpattern) func=None for item in URLpattern: if path==item[0]: func=item[1] break if func: return [func(environ)] else: return [b"404
"]s=make_server("127.0.0.1",8083,application)
重点
web框架:wsgiref模块的使用 from wsgiref.simple_server import make_server def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'Hello, web!
'] httpd = make_server('', 8080, application) print('Serving HTTP on port 8000...') # 开始监听HTTP请求: httpd.serve_forever()