前言
什么是Web,维基百科的描述如下:
万维网(英语:World Wide Web),亦作“WWW”、“Web”,是一个透过互联网访问的,由许多互相链接的超文本组成的系统。
—— 维基百科
我们的生活现在已经离不开互联网,我们日常使用的互联网服务中,其中的相当的一部分是Web系统所提供的,我们每天使用的搜索,新闻,购物等服务,其背后的实现,也是基于Web的技术栈,但是,Web系统究竟是怎么运作的呢?接下来我们就一起来实现一个最简单的Web服务器(使用python3),我们这里说的Web服务器是指HTTP服务器。
2
socket
socket是一种操作系统提供的进程间通信机制,简单来讲,socket是用来通信用的,它实现了TCP与UDP协议,Web系统是基于HTTP协议的,所以这里,我们使用socket来实现一个简单的Web服务器。
3
使用Python来实现一个最简单的HTTP服务器
1、新建一个文件夹WebServer,并在该文件下新建一个文件server.py
2、打开该文件,写入以下代码:
# 导入socket包 import socket # 服务器IP与端口 HttpPort = 18080 HttpHost = ('localhost', HttpPort) # 头部信息 HttpResponseHeader = '''HTTP/1.1 200 OK Content-Type: text/html;charset=UTF-8 ''' # Header与Body分隔符 LineSeparator = ' ' # HTTP响应 HttpResponseBody = '' # 创建基于IPV4 TCP的socket ServerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # socket的绑定与监听 ServerSocket.bind(HttpHost) ServerSocket.listen(100) print("server is running") # 处理客户端连接 while True: HttpResponseBody = '很开心遇见你 :)' Client, Address = ServerSocket.accept() Request = Client.recv(1024).decode(encoding='utf-8') Client.sendall((HttpResponseHeader + HttpResponseBody).encode(encoding='utf-8')) Client.close()
3、我们在该目录下打开shell,并输入以下命令:
python3 server.py
我们可以看到以下输出:
我们打开浏览器,并在地址栏输入http://127.0.0.1:18080,可以看到以下输出:
上面的这一段代码的效果,我们已经看到了,但是,这段代码究竟做了什么呢?
TCP是传输层的协议,HTTP是应用层的协议,HTTP协议基于TCP协议,我们通过socket,建立起了客户端到服务器的TCP连接,服务器先进行监听,客户端发起一个连接,服务器收到该连接请求之后并同意建立连接,之后客户端向服务端发起HTTP请求,我们的服务端对该HTTP请求进行一定的解析之后,发送响应给客户端,然后关闭连接,这就完成了一次HTTP请求。
4
实现解析URL参数与用户提交的表单
1、我们更新server.py的代码如下:
# 导入socket包 import socket # 服务器IP与端口 HttpPort = 18080 HttpHost = ('localhost', HttpPort) # 头部信息 HttpResponseHeader = '''HTTP/1.1 200 OK Content-Type: text/html;charset=UTF-8 ''' # Header与Body分隔符 LineSeparator = ' ' # HTTP响应 HttpResponseBody = '' # 创建基于IPV4 TCP的socket ServerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # socket的绑定与监听 ServerSocket.bind(HttpHost) ServerSocket.listen(100) print("server is running at http://localhost:%d" % HttpPort) # 获取HTTP请求报头 def get_headers(request): # 分隔符切割 headers_array = request.split(' ') # HTTP请求头首行 是请求方法 请求路径 HTTP协议版本 headers = {} for header_item in headers_array[1:]: item_ = header_item.split(': ') headers[item_[0]] = item_[1] return headers # 获取URL参数 def get_get_args(request_url): get_args_arr = request_url[request_url.find('?')+1:].split('&') # print(get_args_arr) get_args = {} try: for get_item in get_args_arr: item_ = get_item.split('=') get_args[item_[0]] = item_[1] return get_args except: return {} # 获取POST表单参数 def get_post_args(request_body): post_args_arr = request_body.split('&') post_args = {} for post_item in post_args_arr: item_ = post_item.split('=') post_args[item_[0]] = item_[1] return post_args # 处理客户端连接 while True: Client, Address = ServerSocket.accept() # 客户端的HTTP请求 Request = Client.recv(1024).decode(encoding='utf-8') # 将请求分为报头与主体 RequestText = Request.split(LineSeparator) # 报头 RequestHeader = RequestText[0] # 主体 RequestBody = RequestText[1] # 请求方法 RequestMethod = RequestHeader.split(' ')[0] # 请求路径 RequestUrl = RequestHeader.split(' ')[1] # 请求头部 RequestHeaders = get_headers(RequestHeader) # 响应清空 HttpResponseBody = '' # GET请求处理 if RequestMethod == 'GET': HttpResponseBody += '''<html> Your method is GET and your request url is ''' + RequestUrl + ''' <br> The following are you headers :<br> ''' for item in RequestHeaders.items(): HttpResponseBody += ('key :' + item[0] + ",value :" + item[1] + '<br>') HttpResponseBody += 'There are your url args :<br>' URL_args = get_get_args(RequestUrl) for item in URL_args.items(): HttpRes
2、然后执行: python3 server.py
3、我们可以看到能够如下显示:
GET请求:
POST请求:
这里我们主要是对参数进行了解析,然后并对其进行了显示,现实中,我们使用搜索引擎的时候,关键字一般都是通过GET方法来加上参数,需要用户提交用户名密码或者其他表单时,我们一般使用POST方法,有关更多的HTTP资料,请参考这里MDN 。