简单的 HTTP 服务器搭建 | 学习笔记

简介: 快速学习简单的 HTTP 服务器搭建,介绍了简单的 HTTP 服务器搭建系统机制, 以及在实际应用过程中如何使用。

开发者学堂课程【Python 入门 2020年版简单的 HTTP 服务器搭建】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/639/detail/10477


简单的HTTP服务器搭建

 

内容介绍:

一、学习目标

二、使用谷歌/火狐浏览器分析

三、概念

四、结合实例百度网站编写服务器

 

一、学习目标

1.能够说出什么是 HTTP 协议

2.能够手写代码搭建一个 HTTP 服务器

3.了解 WSGI 接口

4.能够看懂自定义 WSGI 服务器

5.能够使用requests插件发送请求

今天学习搭建网站,但是这个网站能力差、功能不全、性能不好,只是简单讲一下框架的实现理论。

 

二、使用谷歌/火狐浏览器分析

1.在 Web 应用中,服务器把网页传给浏览器,实际上就是把网页的 HTML 代码发送给浏览器,让浏览器显示出来。而浏览器和服务器之间的传输协议是 HTTP,所以:

HTML 是种用来定义网页的文本,会 HTML, 就可以编写网页;

HTTP 是在网络上传输 HTML 的协议,用于浏览器和服务器的通信。

Chrome 浏览器提供了一套完整地调试工具,非常适合 Web 开发。

安装好 Chrome 浏览器后,打开 Chrome,在菜单中选择"视图",“开发者", “开发者工具", 就可以显示开发者工具: 

2.说明

Elements 显示网页的结构

Network 显示浏览器和服务器的通信

我们点 Network,确保第一个小红灯亮着,Chrome 就会记录所有浏览器和服务器之间的通信:


三、概念

HTTP 协议:Hyper Text Transfer Protocol 超文本传输协议

协议的作用就是用来传输超文本 HTML(Hyper Text Markup Language)

HTML:超文本标记语言

HTTP:用来传输超文本的一个协议

有什么规则

我们上网是干什么,怎么写一个网站呢

客户端 Client

HTTP 服务器 Server

C/S架构 client-server    手机淘宝 APP 就是一个客户端

B/S架构 browser-server  浏览器访问淘宝

不管是 APP 还是浏览器我们都可以把它们看作客户端。不管是什么结构就是客户端不一样,服务器的实现都是一样的,返回的数据也是一样的。

如果前后端分离就返回 json 字符串,比如’{“name”:”zhangsan ”}’

图片7.png


四、结合实例百度网站编写服务器

在浏览器里输入192.168.31.199,是不能正常访问操作的。

上网,两个电脑要通信就是网络通信,用 socket 写,其实就是 socket 链接。

1.代码:

import socket

#HTTP服务器都是基于TCP的socket

server_socket=socket.socket(socket.AF_INEF, socket.SOCK_STREAM)

server_socket.bind((‘192.168.31.199’,9090))

server_socket.listen(128)

x=server_socket.accept()

print(x)

用网络调试助手连接一下,会收到消息,获取的数据是一个元祖,元祖里有两个元素,第0个元素是客户端的socket链接,第1个元素是客户端的ip地址和端口号。

2.代码:

import socket

#HTTP服务器都是基于TCP的socket

server_socket=socket.socket(socket.AF_INEF, socket.SOCK_STREAM)

server_socket.bind((‘192.168.31.199’,9090))

server_socket.listen(128)

#获取的数据是一个元祖,元祖里有两个元素

#第0个元素是 客户端的 socket 链接

#第1个元素是 客户端的 ip 地址和端口号

拆包一下:

client_socket,client_addr=server_socket.accept()

#从客户端的 socket 里获取数据

data=client_socket.recv(1024).decode(‘utf8’)

print(data)

在网络调试助手,数据发送处发送 ok,就能在写的服务器中收到 ok。要对底层开发有所认识,但以后写不会用 socket。

128是什么意思,当服务器能够处理1000个,但如果突然同时来了1002个,那这两个就处理不了,需要排队,如果来了1120个,120个也要排队,如果来了1130个,有130个不能处理,128就是排队的长度,剩下的2个就连不进来了。

刚才用网络调试工具访问了服务器,发消息,那能不能用代码发送,以前写过用代码发送一个TCP的请求,自己写了一个服务器。

现在不用客户端,用浏览器。程序已经运行到192.168.31.199:9090(9090是端口号),这里可以用网络调试工具访问,只要能发送一个请求就可以,我们也可以自己写代码发送请求,也能使用浏览器发送请求。

 图片8.png

用浏览器是可以收到请求的

图片9.png

图片10.png

上图是 HTTP 的请求头

打开控制栏的两种方法(使用的谷歌浏览器):

(1)右击找到检查

图片11.png

 

2右上角找到浏览器的设置——更多工具——开发者工具

图片12.png

打开后如下图:

图片13.png

先把控制栏打开,这有 Elements,它是界面上的元素。比如打开百度新闻点击一个内容控制栏就会标对应的代码,右击代码选择“delete element”就能删除对应内容,但不是真正删除,只是在自己界面上的元素,刷新删除的元素就会恢复。

我们今天要关注的重点是 network,访问网站时我们发了好多个请求,其中有一个是 www.baidu.com,有的时候我们打开以后会没有了,只需要重新刷新网站,然后再右击检查打开控制栏。经常会发现 network 没有东西,原因是网络没有连接,再刷新一下页面就可以看到了。进入“www.baidu.com”,其中“General”是概要、通用的东西,大家可以简单地看一看,我们先不看这个,先把它收起来。里面有“General”、“Response Headers”、“Request Headers”,后两个分别是“响应头”和“请求头”。

 图片14.png

 图片15.png

也就是说发的要有规范,返回的也要有规范。

服务器没有给客户端返回消息,9090是空的。

怎么给客户端返回消息:

import socket

#HTTP服务器都是基于TCP的socket

server_socket=socket.socket(socket.AF_INEF, socket.SOCK_STREAM)

server_socket.bind((‘192.168.31.199’,9090))

server_socket.listen(128)

#获取的数据是一个元祖,元祖里有两个元素

#第0个元素是 客户端的socket链接

#第1个元素是 客户端的ip地址和端口号

拆包一下:

client_socket,client_addr=server_socket.accept()

#从客户端的socket里获取数据

data=client_socket.recv(1024).decode(‘utf8’)

#给客户端返回消息

client_socket.send(“hello world”.encode(‘utf8’))

print(data)

这时我们运行一下能不能收到

图片16.png

返回内容之前,需要先设置 HTTP 响应头

怎么设置呢,我们先看一下标准的实例:

点击“view source”(在没点“view source”时,显示的是解析后的内容)就可以看到它的响应头。

图片17.png

import socket

#HTTP服务器都是基于TCP的socket

server_socket=socket.socket(socket.AF_INEF, socket.SOCK_STREAM)

server_socket.bind((‘192.168.31.199’,9090))

server_socket.listen(128)

#获取的数据是一个元祖,元祖里有两个元素

#第0个元素是 客户端的socket链接

#第1个元素是 客户端的ip地址和端口号

拆包一下:

client_socket,client_addr=server_socket.accept()

#从客户端的socket里获取数据

data=client_socket.recv(1024).decode(‘utf8’)

print(‘接收到的数据{}’.format(data))

#返回内容之前,需要先设置HTTP响应头

#设置一个响应头就换一行

client_socket.send(‘HTTP/1.1 200 OK\n’.encode(‘utf8’))  #HTTP/1.1 200 OK是必须写的,是格式

#所有的响应头设置完成以后,再换行

client_socket.send(‘\n’.encode(‘utf8’))

#发送内容

client_socket.send(“hello world”.encode(‘utf8’))

运行结果:

图片18.png

再加一个响应头:client_socket.send(‘content-type:text/html’.encode(‘utf8’))

每一个头写完以后都要换行,所有的头写完以后再来一个换行,紧跟着才是消息。

import socket

#HTTP 服务器都是基于 TCP 的 socket

server_socket=socket.socket(socket.AF_INEF, socket.SOCK_STREAM)

server_socket.bind((‘192.168.31.199’,9090))

server_socket.listen(128)

#获取的数据是一个元祖,元祖里有两个元素

#第0个元素是 客户端的socket链接

#第1个元素是 客户端的ip地址和端口号

拆包一下:

client_socket,client_addr=server_socket.accept()

#从客户端的socket里获取数据

data=client_socket.recv(1024).decode(‘utf8’)

print(‘接收到的数据{}’.format(data))

OK 是必须写的,是格式

client_socket.send(‘content-type:text/html’.encode(‘utf8’))

#所有的响应头设置完成以后,再换行

client_socket.send(‘\n’.encode(‘utf8’))

#发送内容

client_socket.send(“hello world”.encode(‘utf8’))

运行结果:同上,出现 hello world。

这个代码是放在自己电脑上的,我现在把它放到更大的地方,放到腾讯的云服务器上。

但注意地址要改成‘0.0.0.0’,端口号不能写死,地址的区别一会再讲。

运行起来:

图片19.png

我的云端服务器的 ip 地址是:106.54.81.174:9090

可以访问到 hello world

这个不止是我能访问,同学们也能访问,但是我这服务器是一次性的,一次就崩。

修改一下代码:

import socket

#HTTP服务器都是基于TCP的socket

server_socket=socket.socket(socket.AF_INEF, socket.SOCK_STREAM)

server_socket.bind((‘0.0.0.0’,8080))

server_socket.listen(128)

#获取的数据是一个元祖,元祖里有两个元素

#第0个元素是 客户端的 socket 链接

#第1个元素是 客户端的 ip 地址和端口号

拆包一下:

client_socket,client_addr=server_socket.accept()

#从客户端的socket里获取数据

data=client_socket.recv(1024).decode(‘utf8’)

print(‘接收到{}的数据{}’.format(client_addr[0],data))

#返回内容之前,需要先设置HTTP响应头

#设置一个响应头就换一行

client_socket.send(‘HTTP/1.1 200 OK\n’.encode(‘utf8’))  #HTTP/1.1 200 OK是必须写的,是格式

client_socket.send(‘content-type:text/html’.encode(‘utf8’))

#所有的响应头设置完成以后,再换行

client_socket.send(‘\n’.encode(‘utf8’))

#发送内容

client_socket.send(“hello world”.encode(‘utf8’))

现在同学们可以输入地址:106.54.81.174:8080可以访问到 hello world

再改成9090也可以访问到,我这个代码只能接收一次,我没有写死循环,一个同学访问到,其他同学就访问不到了。

换一下端口号,写个死循环:

import socket

port=int(input(‘请输入端口号:’))

#HTTP 服务器都是基于 TCP 的 socket

server_socket=socket.socket(socket.AF_INEF, socket.SOCK_STREAM)

server_socket.bind((‘0.0.0.0’,port))

server_socket.listen(128)

print(‘server is running at 0.0.0.0:{}’.format(port))

#获取的数据是一个元祖,元祖里有两个元素

#第0个元素是 客户端的 socket 链接

#第1个元素是 客户端的 ip 地址和端口号

while True:

client_socket,client_addr=server_socket.accept()

#从客户端的 socket 里获取数据

data=client_socket.recv(1024).decode(‘utf8’)

print(‘接收到{}的数据{}’.format(client_addr[0],data))

#返回内容之前,需要先设置 HTTP 响应头

#设置一个响应头就换一行

client_socket.send(‘HTTP/1.1 200 OK\n’.encode(‘utf8’))  #HTTP/1.1 200 OK 是必须写的,是格式

client_socket.send(‘content-type:text/html’.encode(‘utf8’))

#所有的响应头设置完成以后,再换行

client_socket.send(‘\n’.encode(‘utf8’))

#发送内容

client_socket.send(“hello world”.encode(‘utf8’))

现在把代码上传到服务器,让大家玩一玩,原理还是很简单的。

图片20.png

是可以访问到的,端口号我改成9090,不断变,因为一直提示占用,这个服务器比较脆弱。

现在不返回 hello world,我把你们的 ip 地址返回去。不只是电脑可以访问,手机也可以。

图片21.png

 

相关文章
|
3天前
|
缓存 安全 算法
网络原理 HTTP _ HTTPS
网络原理 HTTP _ HTTPS
10 0
|
2月前
|
网络协议 前端开发 JavaScript
网络原理 - HTTP/HTTPS(1)
网络原理 - HTTP/HTTPS(1)
|
2月前
|
存储 Web App开发 API
网络原理 - HTTP/HTTPS(3)
网络原理 - HTTP/HTTPS(3)
|
2月前
|
安全 算法 数据安全/隐私保护
网络原理 - HTTP/HTTPS(5)
网络原理 - HTTP/HTTPS(5)
|
2月前
|
Web App开发 应用服务中间件 nginx
网络原理 - HTTP/HTTPS(4)
网络原理 - HTTP/HTTPS(4)
|
2月前
|
缓存 JavaScript 安全
网络原理 - HTTP/HTTPS(2)
网络原理 - HTTP/HTTPS(2)
|
5月前
|
前端开发 JavaScript 应用服务中间件
个人博客网站如何实现https重定向(301)到http
对于个人网站站注册比较少的,服务器配置不是很好的,没必要https,https跳转到http是要时间的,会影响网站打开的速度。免费的https每年都要更换。
76 2
|
5月前
|
安全 前端开发 搜索推荐
前端知识笔记(六)———HTTP和HTTPS有什么区别?
前端知识笔记(六)———HTTP和HTTPS有什么区别?
67 0
|
5月前
|
前端开发 JavaScript
前端知识笔记(六)———nodejs发起http或https请求
前端知识笔记(六)———nodejs发起http或https请求
31 0
|
Web App开发 JSON 网络协议
简单的 HTTP 服务器搭建 | 学习笔记
快速学习简单的 HTTP 服务器搭建,介绍了简单的 HTTP 服务器搭建系统机制, 以及在实际应用过程中如何使用。
1398 0
简单的 HTTP 服务器搭建 | 学习笔记