1. HTTP格式

每个HTTP请求和响应都遵循相同的格式,一个HTTP包含Header和Body两部分,其中Body是可选的。HTTP协议是一种文本协议,所以,它的格式也非常简单。

1.1 HTTP GET请求的格式:

GET /path HTTP/1.1
Header1: Value1
Header2: Value2
Header3: Value3

1.2 HTTP POST请求的格式:

POST /path HTTP/1.1
Header1: Value1
Header2: Value2
Header3: Value3 body data goes here...

当遇到连续两个\r\n时,Header部分结束,后面的数据全部是Body。

1.3 HTTP响应的格式:

HTTP/1.1 200 OK
Header1: Value1
Header2: Value2
Header3: Value3 body data goes here...

HTTP响应如果包含body,也是通过\r\n\r\n来分隔的。

请再次注意,Body的数据类型由Content-Type头来确定,如果是网页,Body就是文本,如果是图片,Body就是图片的二进制数据。

当存在Content-Encoding时,Body数据是被压缩的,最常见的压缩方式是gzip,所以,看到Content-Encoding: gzip时,需要将Body数据先解压缩,才能得到真正的数据。压缩的目的在于减少Body的大小,加快网络传输。

2. Web静态服务器-显示固定的页面

import socket

def handle_client(new_client):
"""处理客户端请求""" recv_data = new_client.recv(1024) print(recv_data) # 组装响应的内容
response_headers = "HTTP/1.1 200 OK\r\n"
response_headers += "\r\n"
response_body = "6666" response = response_headers + response_body
new_client.send(response.encode("utf-8")) new_client.close() def main(): # 创建套接字
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定本地消息
tcp_socket_server.bind(("", 8090)) # 套接字由主动变被动
tcp_socket_server.listen(128) while True: # 接收新的请求
new_client, client_addr = tcp_socket_server.accept() handle_client(new_client) # 关闭套接字
tcp_socket_server.close() if __name__ == "__main__": main()

如上的代码仅仅只是向浏览器发送了简单的文本内容:6666

在浏览器中访问:

3. Web静态服务器-显示需要的页面

import socket
import re def handle_client(new_client):
"""处理客户端请求""" recv_data = new_client.recv(1024).decode("utf-8") # GET / HTTP/1.1
request_header_lines = recv_data.splitlines()
for line in request_header_lines:
print(line)
http_request_line = request_header_lines[0];
get_file_name = re.match("[^/]+(/[^ ]*)", http_request_line).group(1)
print("file name is -> " + get_file_name) # print(recv_data)
if get_file_name == "/":
get_file_name = "/index.html" root_path = "./html"
get_file_name = root_path + get_file_name;
try:
f = open(get_file_name, "rb")
except:
response_headers = "HTTP/1.1 404 NOT FOUND\r\n"
response_headers += "\r\n"
response_body = b"page not found"
else: # 组装响应的内容
response_headers = "HTTP/1.1 200 OK\r\n"
response_headers += "\r\n"
response_body = f.read()
f.close() new_client.send(response_headers.encode("utf-8"))
new_client.send(response_body) new_client.close() def main(): # 创建套接字
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定本地消息
tcp_socket_server.bind(("", 8090)) # 套接字由主动变被动
tcp_socket_server.listen(128) while True: # 接收新的请求
new_client, client_addr = tcp_socket_server.accept() handle_client(new_client) # 关闭套接字
tcp_socket_server.close() if __name__ == "__main__": main()

在浏览器中访问:

4. Web静态服务器-多进程版

import socket
import re
import multiprocessing def handle_client(new_client):
"""处理客户端请求""" recv_data = new_client.recv(1024).decode("utf-8") # GET / HTTP/1.1
request_header_lines = recv_data.splitlines()
for line in request_header_lines:
print(line)
http_request_line = request_header_lines[0];
get_file_name = re.match("[^/]+(/[^ ]*)", http_request_line).group(1)
print("file name is -> " + get_file_name) # print(recv_data)
if get_file_name == "/":
get_file_name = "/index.html" root_path = "./html"
get_file_name = root_path + get_file_name;
try:
f = open(get_file_name, "rb")
except:
response_headers = "HTTP/1.1 404 NOT FOUND\r\n"
response_headers += "\r\n"
response_body = b"page not found"
else: # 组装响应的内容
response_headers = "HTTP/1.1 200 OK\r\n"
response_headers += "\r\n"
response_body = f.read()
f.close() new_client.send(response_headers.encode("utf-8"))
new_client.send(response_body) new_client.close() def main(): # 创建套接字
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定本地消息
tcp_socket_server.bind(("", 8090)) # 套接字由主动变被动
tcp_socket_server.listen(128) while True: # 接收新的请求
new_client, client_addr = tcp_socket_server.accept() p = multiprocessing.Process(target=handle_client, args=(new_client,))
p.start() new_client.close() # 关闭套接字
tcp_socket_server.close() if __name__ == "__main__": main()

5. Web静态服务器-多线程版

import socket
import re
import threading def handle_client(new_client):
"""处理客户端请求""" recv_data = new_client.recv(1024).decode("utf-8") # GET / HTTP/1.1
request_header_lines = recv_data.splitlines()
for line in request_header_lines:
print(line)
http_request_line = request_header_lines[0];
get_file_name = re.match("[^/]+(/[^ ]*)", http_request_line).group(1)
print("file name is -> " + get_file_name) # print(recv_data)
if get_file_name == "/":
get_file_name = "/index.html" root_path = "./html"
get_file_name = root_path + get_file_name;
try:
f = open(get_file_name, "rb")
except:
response_headers = "HTTP/1.1 404 NOT FOUND\r\n"
response_headers += "\r\n"
response_body = b"page not found"
else: # 组装响应的内容
response_headers = "HTTP/1.1 200 OK\r\n"
response_headers += "\r\n"
response_body = f.read()
f.close() new_client.send(response_headers.encode("utf-8"))
new_client.send(response_body) new_client.close() def main(): # 创建套接字
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定本地消息
tcp_socket_server.bind(("", 8090)) # 套接字由主动变被动
tcp_socket_server.listen(128) while True: # 接收新的请求
new_client, client_addr = tcp_socket_server.accept() t = threading.Thread(target=handle_client, args=(new_client,))
t.start() # 关闭套接字
tcp_socket_server.close() if __name__ == "__main__": main()

6. Web静态服务器-gevent版

import socket
import re
import gevent
from gevent import monkey monkey.patch_all() def handle_client(new_client):
"""处理客户端请求""" recv_data = new_client.recv(1024).decode("utf-8") # GET / HTTP/1.1
request_header_lines = recv_data.splitlines()
for line in request_header_lines:
print(line)
http_request_line = request_header_lines[0];
get_file_name = re.match("[^/]+(/[^ ]*)", http_request_line).group(1)
print("file name is -> " + get_file_name) # print(recv_data)
if get_file_name == "/":
get_file_name = "/index.html" root_path = "./html"
get_file_name = root_path + get_file_name;
try:
f = open(get_file_name, "rb")
except:
response_headers = "HTTP/1.1 404 NOT FOUND\r\n"
response_headers += "\r\n"
response_body = b"page not found"
else: # 组装响应的内容
response_headers = "HTTP/1.1 200 OK\r\n"
response_headers += "\r\n"
response_body = f.read()
f.close() new_client.send(response_headers.encode("utf-8"))
new_client.send(response_body) new_client.close() def main(): # 创建套接字
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定本地消息
tcp_socket_server.bind(("", 8090)) # 套接字由主动变被动
tcp_socket_server.listen(128) while True: # 接收新的请求
new_client, client_addr = tcp_socket_server.accept() g = gevent.spawn(handle_client, new_client)
g.join() # 关闭套接字
tcp_socket_server.close() if __name__ == "__main__": main()

http协议、web服务器、并发服务器(上)的更多相关文章

  1. web服务器-并发服务器2

    阅读目录 1.Web静态服务器-5-非堵塞模式 2.Web静态服务器-6-epoll 3.Web静态服务器-7-gevent版 4.知识扩展-C10K问题 一.Web静态服务器-5-非堵塞模式 单进程 ...

  2. 14_Web服务器-并发服务器

    1.服务器概述 1.硬件服务器(IBM,HP): 主机 集群 2.软件服务器(HTTPserver Django flask): 网络服务器,在后端提供网络功能逻辑处理数据处理的程序或者架构等 3.服 ...

  3. Python复习笔记(十)Http协议--Web服务器-并发服务器

    1. HTTP协议(超文本传输协议) 浏览器===>服务器发送的请求格式如下:(浏览器告诉服务器,浏览器的信息) GET / HTTP/1.1 Host: www.baidu.com Conne ...

  4. Web服务器-并发服务器-Epoll(3.4.5)

    @ 目录 1.介绍 2.代码 关于作者 1.介绍 epoll是一种解决方案,nginx就是用的这个 中心思想:不要再使用多进程,多线程了,使用单进程,单线程去实现并发 在上面博客实现的代码中使用过的轮 ...

  5. Web服务器-并发服务器-单进程单线程非堵塞方式(3.4.3)

    @ 目录 1.分析 2.代码 关于作者 1.分析 当socket去监听的时候,是堵塞的状态 通过tcp_sever_socket.setblocking(False)去设置不堵塞 当socket发现没 ...

  6. Web服务器-并发服务器-长连接(3.4.4)

    @ 目录 1.说明 2.代码 关于作者 1.说明 每次new_socket都被强制关闭,造成短连接 所提不要关闭套接字 但是不关闭的话,浏览器不知道发完没有啊 此时用到header的属性Content ...

  7. Web服务器-并发服务器-协程 (3.4.2)

    @ 目录 1.分析 2.代码 关于作者 1.分析 随着网站的用户量越来愈多,通过多进程多线程的会力不从心 使用协程可以缓解这一问题 只要使用gevent实现 2.代码 from socket impo ...

  8. Web服务器-并发服务器-多进程(3.4.1)

    @ 目录 1.优化分析 2.代码 3. 关于作者 1.优化分析 在单进程的时候,相当于 是来一个客户,派一个人去服务一下 效率低,现在使用多进程来服务 假设场景 100个人同时访问页面 单进程:一次处 ...

  9. linux学习之多高并发服务器篇(一)

    高并发服务器 高并发服务器 并发服务器开发 1.多进程并发服务器 使用多进程并发服务器时要考虑以下几点: 父最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符) 系统内创建进程 ...

  10. 手把手让你实现开源企业级web高并发解决方案(lvs+heartbeat+varnish+nginx+eAccelerator+memcached)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://freeze.blog.51cto.com/1846439/677348 此文凝聚 ...

随机推荐

  1. Python学习笔记-基础2

    1.列表list 列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现. 1.定义列表 names = ["Ronaldo","Messi" ...

  2. Jenkins初级使用过程中的异常处理(1)

    在使用Jenkins一些基本功能的时候,或者说是基本插件的时候,会遇到各种各样的报错.这里就设想模拟一下,重现一下以前遇到过的问题,记录一下.虽说是Jenkins使用过程中出现这样的问题,但实际上可以 ...

  3. 干货——详解Java中的关键字

    在平时编码中,我们可能只注意了这些static,final,volatile等关键字的使用,忽略了他们的细节,更深层次的意义. 本文总结了Java中所有常见的关键字以及一些例子. static 关键字 ...

  4. Python math库常用函数

    math库常用函数及举例: 注意:使用math库前,用import导入该库>>> import math 取大于等于x的最小的整数值,如果x是一个整数,则返回x>>> ...

  5. Java学习笔记二:数据类型II

    GitHub代码练习地址:https://github.com/Neo-ML/JavaPractice/blob/master/Intpractice3.java 一  Java中的数据类型 Java ...

  6. 第50节:Java的当中的泛型

    Java当中的泛型 01 import java.util.ArrayList; import java.util.List; public class Demo{ public static voi ...

  7. iTerm2 使用笔记

    iTerm2 使用了1年多了,一些功能其实还没有主动去发现,这次接着项目忙完的空闲时间整理一下tips,提高工作效率,方便以后查阅. 一.几个术语 从小到大:session > pane > ...

  8. 在 React、Vue项目中使用 SVG

    在一些现代的扁平化设计网站,特别是移动端网站,经常会包含许多简单而清晰的小图标,例如网站图标.用户的默认头像.移动端网页首页底部固定的切换栏等,这些小图标一般都是由美工做好,可能会放到精灵图上,前端再 ...

  9. H5在WebView上开发小结

    背景 来自我司业务方要求,需开发一款APP.但由于时间限制,只能采取套壳app方式,即原生app内嵌webview展示前端页面.本文主要记述JavaScript与原生app间通信,以及内嵌webvie ...

  10. 五分钟了解node,cnpm和yarn

    1.静态网页和动态网页 动态网页:数据可以进行交互,动态改变数据 2.node node是基于chrome的V8引擎的javascript的运行环境,node中的事件机制以及非阻塞式的I/O式模式,使 ...