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. day21_雷神_django第四天

    django第四天 1.form组件 解决两个事情: 不想重复提交,数据重置: 校验规则 流程: (1) 创建form组件对应的类,比如LoginForm (2) views.login: if ge ...

  2. 深入-FastReport TfrxReport组件使用

    [翻译] FastReport TfrxReport组件使用   一:加载和保存报表 报表默认保存在项目窗体文件中,大多数情况下,没有更多的操作要深圳市, 因此,你不需要采取特别措施来载入报告.如果你 ...

  3. Dubbo 源码分析 - 服务导出

    1.服务导出过程 本篇文章,我们来研究一下 Dubbo 导出服务的过程.Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可 ...

  4. Hive数据仓库之快速入门

    Hive定位:ETL(数据仓库)工具 将数据从来源端经过抽取(extract).转换(transform).加载(load)至目的端的工具,如像:kettle 有关Hive数据导入导出mysql的问题 ...

  5. 2.AsyncQueryHandler、内容提供者

    会话页面 Test :测试 public class Test extends AndroidTestCase{ public void test(){ Uri uri = Uri.parse(&qu ...

  6. 吴恩达机器学习笔记44-核函数(Kernels)

    回顾我们之前讨论过可以使用高级数的多项式模型来解决无法用直线进行分隔的分类问题: 为了获得上图所示的判定边界,我们的模型可能是

  7. Apache Lucene全局搜索引擎入门教程

    Lucene简介 Lucent:Apache软件基金会Jakarta项目组的一个子项目,Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻.在Java开发环境里Lucene是一个成熟 ...

  8. 解决Java中There is no getter for property XXX'XXX' in 'class XXX'的问题

    当你出现There is no getter for property XXX'XXX' in 'class XXX'时, 就是在你的这个类中没有找到你这个属性. 检查两个地方 1.你的返回值类型是否 ...

  9. Merge branch 'master' of xxx error

    Merge branch 'master' of xxx Please enter a commit message to explain why this merge is necessary,es ...

  10. Abp + MongoDb 改造默认的审计日志存储位置

    一.背景 在实际项目的开发当中,使用 Abp Zero 自带的审计日志功能写入效率比较低.其次审计日志数据量中后期十分庞大,不适合与业务数据存放在一起.所以我们可以重新实现 Abp 的 IAuditi ...