租个服务器自己写自己的网站,自己写一个web服务器(1)

news/2024/5/11 16:35:36/文章来源:https://blog.csdn.net/weixin_28938385/article/details/119585566

web服务器

一个运行在物理服务器上的网络服务器,它等待客户端发送的请求。当它收到一个请求,它会生成一个回复并传回到客户端。一个客户端和服务器的通信可以通过HTTP协议实现。

HelloWorld

# coding: utf-8

import socket

HOST, PORT = '', 8888

listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

listen_socket.bind((HOST, PORT))

listen_socket.listen(1)

print 'Serving HTTP on port %s ...' % PORT

while True:

client_connection, client_address = listen_socket.accept()

request = client_connection.recv(1024)

print request

http_response = """\

HTTP/1.1 200 OK

Hello, World!

"""

client_connection.sendall(http_response)

client_connection.close()

上面的代码会监听本机的8888端口,并且对于所有的请求都返回一个HTTP Response。

使用tenlent来模拟浏览器发起一个网络请求

[图片上传失败...(image-bdc02e-1551094101777)]

一个HTTP请求由HTTP方法(GET),路径(/)指向服务器的一个“页面”和协议版本(HTTP/1.1)组成。

一个HTTP响应由 1. 状态行 HTTP/1.1(协议) 200 OK(返回码), 2. 空白行 3. HTTP响应主体(HelloWorld)组成

总地来说就是:

web服务器创建一个监听socket持续地接受新的连接。

客户端发起一个TCP连接,然后成功建立连接之后,客户端发出一个HTTP请求给服务器

服务器用HTTP响应来做回复,最后呈现给用户。

建立TCP连接的过程中客户端和服务器都使用了 socket。

WSGI

我们刚刚建立了一个简单的Web服务器,对所有的请求都返回一个HelloWorld。那么,我们应该怎么在刚建立的Web服务器上运行一个Django应用,Flask应用,Torondo应用或者其他框架呢?即:怎么可以在不修改服务器和框架代码的情况下来确保可以在多个框架下运行web服务器呢?

一个Web应用的本质就是:

浏览器发送一个HTTP请求;

服务器收到请求,生成一个HTML文档;

服务器把HTML文档作为HTTP响应的Body发送给浏览器;

浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示

所以,最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。

如果要动态地生成 HTML,我们就需要自己去实现上述的步骤:接受HTTP请求、解析HTTP请求、发送HTTP响应等等都需要手动来完成。

然而我们实际上并不关心这些流程是怎么实现的。正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。

Python Web Server Gateway Interface(简称 WSGI)

WSGI是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。

简单地说:WSGI就像一座桥梁,一边连着用户应用,一遍连着Web服务器

de7db2244c1a

WSGI

所有的现代Web框架都已经实现了WSGI接口,可以在不用对代码作任何修改的情况下就能使服务器和特点的web框架协同工作。其他语言中也有类似的接口,例如 Java 的Servlet API。

一个极简的WSGI服务器实现

# coding: utf-8

import socket

import StringIO

import sys

class WSGIServer(object):

address_family = socket.AF_INET

socket_type = socket.SOCK_STREAM

request_queue_size = 1

def __init__(self, server_address):

# Create a listening socket

# 创建socket,利用socket获取客户端的请求

self.listen_socket = listen_socket = socket.socket(

self.address_family,

self.socket_type

)

# Allow to reuse the same address

# 设置socket的工作模式

listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# Bind

listen_socket.bind(server_address)

# Activate

listen_socket.listen(self.request_queue_size)

# Get server host name and port

host, port = self.listen_socket.getsockname()[:2]

self.server_name = socket.getfqdn(host)

self.server_port = port

# Return headers set by Web framework/Web application

self.headers_set = []

def set_app(self, application):

self.application = application

#启动WSGI server服务,不停的监听并获取socket数据。

def serve_forever(self):

listen_socket = self.listen_socket

while True:

# New client connection

self.client_connection, client_address = listen_socket.accept()

# Handle one request and close the client connection. Then

# loop over to wait for another client connection

self.handle_one_request()

def handle_one_request(self):

self.request_data = request_data = self.client_connection.recv(1024)

# Print formatted request data a la 'curl -v'

print(''.join(

'< {line}\n'.format(line=line)

for line in request_data.splitlines()

))

self.parse_request(request_data)

# Construct environment dictionary using request data

env = self.get_environ()

# It's time to call our application callable and get

# back a result that will become HTTP response body

#给应用传递两个参数,environ,start_response

result = self.application(env, self.start_response)

# Construct a response and send it back to the client

self.finish_response(result)

def parse_request(self, text):

request_line = text.splitlines()[0]

request_line = request_line.rstrip('\r\n')

# Break down the request line into components

(self.request_method, # GET

self.path, # /hello

self.request_version # HTTP/1.1

) = request_line.split()

# 获取environ数据并设置当前server的工作模式

def get_environ(self):

env = {

'wsgi.version': (1, 0),

'wsgi.url_scheme': 'http',

'wsgi.input': StringIO.StringIO(self.request_data),

'wsgi.errors': sys.stderr,

'wsgi.multithread': False,

'wsgi.multiprocess': False,

'wsgi.run_once': False,

'REQUEST_METHOD': self.request_method,

'PATH_INFO': self.path,

'SERVER_NAME': self.server_name,

'SERVER_PORT': str(self.server_port)

}

# The following code snippet does not follow PEP8 conventions

# but it's formatted the way it is for demonstration purposes

# to emphasize the required variables and their values

#

# Required WSGI variables

# Required CGI variables

return env

def start_response(self, status, response_headers, exc_info=None):

# Add necessary server headers

server_headers = [

('Date', 'Tue, 31 Mar 2015 12:54:48 GMT'),

('Server', 'WSGIServer 0.2'),

]

self.headers_set = [status, response_headers + server_headers]

# To adhere to WSGI specification the start_response must return

# a 'write' callable. We simplicity's sake we'll ignore that detail

# for now.

# return self.finish_response

def finish_response(self, result):

try:

status, response_headers = self.headers_set

response = 'HTTP/1.1 {status}\r\n'.format(status=status)

for header in response_headers:

response += '{0}: {1}\r\n'.format(*header)

response += '\r\n'

for data in result:

response += data

# Print formatted response data a la 'curl -v'

print(''.join(

'> {line}\n'.format(line=line)

for line in response.splitlines()

))

self.client_connection.sendall(response)

finally:

self.client_connection.close()

SERVER_ADDRESS = (HOST, PORT) = '', 8888

def make_server(server_address, application):

server = WSGIServer(server_address)

server.set_app(application)

return server

if __name__ == '__main__':

if len(sys.argv) < 2:

sys.exit('Provide a WSGI application object as module:callable')

app_path = sys.argv[1]

_module, _application = app_path.split(':')

module = __import__(_module)

_application = getattr(module, _application)

httpd = make_server(SERVER_ADDRESS, _application)

print('WSGIServer: Serving HTTP on port {port} ...\n'.format(port=PORT))

httpd.serve_forever()

各个方法的意义

init: wsgi server的初始化操作

serve_forever: 可以让wsgi server一直监听客户端请求

handle_one_request: 对每一次请求进行参数解析,包括parse_request和get_environ

start_response: 传递给application的回调函数,根据PEP333,start_response需要包含status, response_headers, exc_info三个参数。status是http的状态码,如“200 OK”,”404 Not Found”。response_headers是一个(header_name, header_value) 元组的列表,在进行application开发时需要注意这点。exc_info通常不需要,直接设置为None即可。具体的一些参数的解释可以参考协议的详细解释。

finish_response: 解析一次请求后,需要关闭socket端口,同时将application返回的data返回至客户端。

flask代码

# coding: utf-8

from flask import Flask

from flask import Response

flask_app = Flask('flaskapp')

@flask_app.route('/hello')

def hello_world():

return Response(

'Hello world from Flask!\n',

mimetype='text/plain'

)

app = flask_app.wsgi_app # 调用Flask暴露的wsgi_app,提供给wsgi server作为application,而不是直接run(port)

启动服务

$ python server_2.py flask_app:app

WSGIServer: Serving HTTP on port 8888 ...

用curl获取Flask 应用生成的消息:

$ curl -v localhost:8888/hello

* Trying 127.0.0.1...

* TCP_NODELAY set

* Connected to localhost (127.0.0.1) port 8888 (#0)

> GET /hello HTTP/1.1

> Host: localhost:8888

> User-Agent: curl/7.64.0

> Accept: */*

>

< HTTP/1.1 200 OK

< Content-Type: text/plain; charset=utf-8

< Content-Length: 24

< Date: Tue, 31 Mar 2015 12:54:48 GMT

< Server: WSGIServer 0.2

<

Hello world from Flask!

* Connection #0 to host localhost left intact

WSGI处理流程

首先,服务器启动然后载入你的web框架/应用提供的‘application’调用

然后,服务器读取请求并解析

然后,根据请求数据创建一个‘environ’ 字典

然后,用‘environ’ 字典调用‘application’,‘start_response’ 做参数同时得到一个响应体

然后,通过‘start_response’ 用‘application’返回的数据和状态及响应头创建一个HTTP响应。

最后,服务器将HTTP响应传回到客户端。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_716260.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

移动虚拟服务器,移动网站需要什么样的虚拟主机空间

移动互联网现在发展的越来越快&#xff0c;随着智能手机的普及&#xff0c;几乎是所有的人都可以使用移动端搜索需要的内容。因此现在越来越多的企业开始注重移动端的网站。那么&#xff0c;我们如果要搭建移动网站需要怎样的虚拟主机空间呢&#xff1f;移动网站需要什么样的虚…

在 Web 服务器或网站上配置 SSL

可以在 Web 服务器或网站上配置安全套接字层 (SSL) 安全功能以检验内容完整性、用户标识和加密网络传输。 Important 只有本地计算机上 Administrators 组的成员才能执行以下过程。作为安全性最佳操作&#xff0c;请使用不属于 Administrators 组的帐户登录计算机&#xff0c;然…

为网站配置SSL

从StartSll申请免费的SSL证书,该网站只支持IE,FireFox,Opera,Safari浏览器,并且注册成功后是以证书来登陆. 注册地址:https://www.startssl.com/?app12 注:注册过程中不要关闭浏览器. 第一步:填写注册信息,注意地址需要详细.如果地址信息不全,会人工发邮件给你,让你发详细地址…

越狱的 iPhone、iPad 通过网站实现一键安装 ipa 格式的 APP 应用

1、已经 越狱 的 iPhone、iPad 设备&#xff0c;当通过其自带的 safari 浏览器访问 ipa 应用下载网站时&#xff0c;利用 itms-services 协议&#xff0c;可以一键安装 ipa 文件的 iOS 应用&#xff0c;例如&#xff1a;<a href"itms-services://?actiondownload-mani…

如何更有效使用 Rational AppScan 扫描大型网站

http://www.ibm.com/developerworks/cn/rational/r-cn-appscanlargewebsite1/index.html Rational AppScan 工作原理 Rational AppScan&#xff08;简称 AppScan&#xff09;其实是一个产品家族&#xff0c;包括众多的应用安全扫描产品&#xff0c;从开发阶段的源代码扫描的 Ap…

让你的网站在IE8的兼容模式下运行

众所周知&#xff0c;微软的Internet Explorer团队一直在致力于将IE8打造为最符合业内标准的浏览器&#xff0c;所不幸的是&#xff0c;当前并非所有的网站都认同这些标准。如果你担心你的网站在IE8的标准模式下不能正常工作的话&#xff0c;下面这些方法也许对你有所帮助&…

bootstrap4 网格布局实例_网站设计师的10个糟糕网页设计实例和常见错误

本文讨论了10个糟糕的网页设计示例和常见错误&#xff0c;以帮助网站设计人员更好地了解好的和坏的网页设计之间的区别。在我们开始之前&#xff0c;我有一个问题&#xff1a;设计网站时&#xff0c;你的首要任务是什么&#xff1f;是吸引人的外观&#xff1f;还是酷炫的效果&a…

建站之星最新0DAY

作者&#xff1a;honker90 //code public function save_profile() {$user_info ParamHolder::get(user, array());//获取数组if (sizeof($user_info) < 0) {$this->assign(json, Toolkit::jsonERR(__(Missing user information!)));return _result;}$passwd_changed f…

配置squid 反向代理提高网站性能

本文旨在介绍 squid 反向代理的工作原理的基础上&#xff0c;指出反向代理技术在提高网站访问速度&#xff0c;增强网站可用性、安全性方面有很好的用途。 现在有许多大型的门户网站都采用 squid 反向代理技术来加速网站的访问速度&#xff0c;可将不同的URL请求分发到后台不同…

网站统计中的数据收集原理及实现

网站统计中的数据收集原理及实现 网站数据统计分析工具是网站站长和运营人员经常使用的一种工具&#xff0c;比较常用的有谷歌分析、百度统计和腾讯分析等等。所有这些统计分析工具的第一步都是网站访问数据的收集。目前主流的数据收集方式基本都是基于javascript的。本文将简要…

构架高性能WEB网站的几点知识

构架高性能WEB网站的几点知识 前言&#xff1a; 对于构架高性能的web网站大家都很感兴趣&#xff0c;本文从几点粗谈高性能web网站需要考虑的问题。 HTML静态化 什么是html静态化&#xff1f; 说得简单点&#xff0c;就是把所有不是.htm或者.html的页面改为.htm或者.html 1.纯…

网站测试自动化系统—数据驱动测试

在前面的文章网站测试自动化系统—基于Selenium和VSTT当中&#xff0c;我简单介绍了使用selenium录制测试步骤&#xff0c;以及优化生成的C#代码&#xff0c;对代码使用面向对象的编程理念进行一些封装&#xff0c;以便规避网站界面更动对测试代码所带来的风险。 在网站测试当中…

网页设计欣赏:20个带给你灵感的国外网站作品

如今这个网络竞争激烈的时代&#xff0c;怎样让网站吸引更多的用户访问是一件非常有挑战的事情&#xff0c;为了设计出更有创意的网页&#xff0c;网页设计师都会去网上寻找创意的灵感。为此&#xff0c;今天这篇文章向大家分享20个从网络上挑选出来的精美绝伦的国外网站设计作…

【应急案例】某云用户网站入侵应急响应

1 情况概述 该案例是前期应急处置的一起因安全问题导致的内网不稳定的情况。写下来&#xff0c;和大家一起讨论应急响应的一些思路及其中间遇到的一些坑&#xff0c;欢迎大牛指点、讨论。 情况是这样的&#xff1a;某用户发现在网络经常出现内网中断的情况&#xff0c;经其内部…

【应急案例】真实网站劫持案例分析

1. 概述 上段时间一直忙于处理大会安全保障与应急&#xff0c;借助公司云悉情报平台&#xff0c;发现并处置几十起网站被劫持的情况。对黑客SEO技术颇有感觉。正好这段时间有时间&#xff0c;把以前遇到比较有趣的案例和大家分享一下。里面很多技术其实早已被玩透&#xff…

【漏洞学习——XSS】Destoon B2B网站管理系统存储xss

漏洞简介 Destoon B2B网站管理系统存储xss&#xff0c;可打后台cookie 我们在修改资料的地方插入xss 查看源代码- - 发现没有做任何的过滤 <td class"tr"><input type"text" size"40" name"post[address]" id"daddre…

网站如何整体换角度

目前ie不支持 body { -webkit-transform: rotate(3deg);/* -moz-transform: rotate(-3deg); -o-transform: rotate(-3deg);*/ /*padding-top: 20px;*/} 网页调灰 html {filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale1);-webkit-filter: grayscale(100%);}

一般企业网站,电商可以完全可以水平拓展的lanmp系统架构

本来不打算把所有的架构方案和基础技术写出&#xff0c;毕竟是吃饭的家伙事&#xff0c;拿这套东西去面试完全可以对付只做过中小网站的经验的开发面试人员&#xff0c;但是我也是从别人的博客和文章学习和实践出来的 如果你没有基础的linux一些软件的知识&#xff0c;你只是开…

【应急基础】————10、windows补丁搜索网站

Windows补丁搜索网站 当你在处理应急响应的时候&#xff0c;你也许碰到一些较新的windows漏洞被理由的情形&#xff0c;在这种情况下&#xff0c;你如何去为第三方提供安全的解决方案呢&#xff1f;Windows漏洞补丁查询网站可以帮助你解决这个问题&#xff01; 网站地址&#…

IIS日志-网站运维的好帮手

阅读目录 开始IIS日志包含了哪些信息IIS日志的配置如何分析IIS日志推荐的IIS日志分析方法IIS日志中的异常记录再谈 scwin32status64寻找性能问题寻找可改进的目标程序架构对IIS日志分析过程的影响 对于一个需要长期维护的网站来说&#xff0c;如何让网站长久稳定运行是件很有意…