python web 服务器学习笔记(四)

在开始新内容之前,我们先解决socket error 98:Address already in use问题

很容易发现可能是由于端口被占用导致的,端口被占用又有很多可能,比如说的关闭你挂上去的服务器,然后又秒开,你会发现这个错误。

此时似乎是由于tcp本身的特性,端口未来得及释放导致的

我们可以通过以下命令查看端口的使用情况,并试着处理它

kill -9 [进程id] 杀死该进程

lsof -i:[端口号]查看端口属于哪个程序

netstrat tln | grep [端口号]查看端口使用情况

嘛。。网上很多方法改socket让它可以重复使用或者restart很快,总觉得对于一个服务器的源码来说加这些不合适(其实我也不会)

然后是Linux关闭防火墙命令

1) 永久性生效,重启后不会复原 开启:chkconfig iptables on 关闭:chkconfig iptables off

2) 即时生效,重启后复原 开启:service iptables start 关闭:service iptables stop

下面要讨论的问题是公共网关接口(CGI)机制,它为web服务器提供一个标准的方式运行外部程序

比如我要运行一个展示时间的python小程序

from datetime import datetime
print ‘‘‘<html>
<body>
<p>Generated {0}</p>
</body>
</html>‘‘‘.format(datetime.now())

下面又是处理方法啦

import sys, os, BaseHTTPServer

#-------------------------------------------------------------------------------

class ServerException(Exception):
    ‘‘‘For internal error reporting.‘‘‘
    pass

#-------------------------------------------------------------------------------

class case_no_file(object):
    ‘‘‘File or directory does not exist.‘‘‘

    def test(self, handler):
        return not os.path.exists(handler.full_path)

    def act(self, handler):
        raise ServerException("‘{0}‘ not found".format(handler.path))

#-------------------------------------------------------------------------------

class case_cgi_file(object):
    ‘‘‘Something runnable.‘‘‘

    def test(self, handler):
        return os.path.isfile(handler.full_path) and                handler.full_path.endswith(‘.py‘)

    def act(self, handler):
        handler.run_cgi(handler.full_path)

#-------------------------------------------------------------------------------

class case_existing_file(object):
    ‘‘‘File exists.‘‘‘

    def test(self, handler):
        return os.path.isfile(handler.full_path)

    def act(self, handler):
        handler.handle_file(handler.full_path)

#-------------------------------------------------------------------------------

class case_directory_index_file(object):
    ‘‘‘Serve index.html page for a directory.‘‘‘

    def index_path(self, handler):
        return os.path.join(handler.full_path, ‘index.html‘)

    def test(self, handler):
        return os.path.isdir(handler.full_path) and                os.path.isfile(self.index_path(handler))

    def act(self, handler):
        handler.handle_file(self.index_path(handler))

#-------------------------------------------------------------------------------

class case_directory_no_index_file(object):
    ‘‘‘Serve listing for a directory without an index.html page.‘‘‘

    def index_path(self, handler):
        return os.path.join(handler.full_path, ‘index.html‘)

    def test(self, handler):
        return os.path.isdir(handler.full_path) and                not os.path.isfile(self.index_path(handler))

    def act(self, handler):
        handler.list_dir(handler.full_path)

#-------------------------------------------------------------------------------

class case_always_fail(object):
    ‘‘‘Base case if nothing else worked.‘‘‘

    def test(self, handler):
        return True

    def act(self, handler):
        raise ServerException("Unknown object ‘{0}‘".format(handler.path))

#-------------------------------------------------------------------------------

class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    ‘‘‘
    If the requested path maps to a file, that file is served.
    If anything goes wrong, an error page is constructed.
    ‘‘‘

    Cases = [case_no_file(),
             case_cgi_file(),
             case_existing_file(),
             case_directory_index_file(),
             case_directory_no_index_file(),
             case_always_fail()]

    # How to display an error.
    Error_Page = """        <html>
        <body>
        <h1>Error accessing {path}</h1>
        <p>{msg}</p>
        </body>
        </html>
        """

    # How to display a directory listing.
    Listing_Page = ‘‘‘        <html>
        <body>
        <ul>
        {0}
        </ul>
        </body>
        </html>
        ‘‘‘

    # Classify and handle request.
    def do_GET(self):
        try:

            # Figure out what exactly is being requested.
            self.full_path = os.getcwd() + self.path

            # Figure out how to handle it.
            for case in self.Cases:
                if case.test(self):
                    case.act(self)
                    break

        # Handle errors.
        except Exception as msg:
            self.handle_error(msg)

    def handle_file(self, full_path):
        try:
            with open(full_path, ‘rb‘) as reader:
                content = reader.read()
            self.send_content(content)
        except IOError as msg:
            msg = "‘{0}‘ cannot be read: {1}".format(self.path, msg)
            self.handle_error(msg)

    def list_dir(self, full_path):
        try:
            entries = os.listdir(full_path)
            bullets = [‘<li>{0}</li>‘.format(e) for e in entries if not e.startswith(‘.‘)]
            page = self.Listing_Page.format(‘\n‘.join(bullets))
            self.send_content(page)
        except OSError as msg:
            msg = "‘{0}‘ cannot be listed: {1}".format(self.path, msg)
            self.handle_error(msg)

    def run_cgi(self, full_path):
        cmd = "python " + full_path
        child_stdin, child_stdout = os.popen2(cmd)
        child_stdin.close()
        data = child_stdout.read()
        child_stdout.close()
        self.send_content(data)

    # Handle unknown objects.
    def handle_error(self, msg):
        content = self.Error_Page.format(path=self.path, msg=msg)
        self.send_content(content, 404)

    # Send actual content.
    def send_content(self, content, status=200):
        self.send_response(status)
        self.send_header("Content-type", "text/html")
        self.send_header("Content-Length", str(len(content)))
        self.end_headers()
        self.wfile.write(content)

#-------------------------------------------------------------------------------

if __name__ == ‘__main__‘:
    serverAddress = (‘‘, 8080)
    server = BaseHTTPServer.HTTPServer(serverAddress, RequestHandler)
    server.serve_forever()

从run_cgi上可以看出这个办法是把该.py放在服务器上运行的。显然会带来一些问题。比如服务器上放了一个会产生死循环的程序,当客户端方知道了有这个程序,客户端可以通过这cgi强行运行它,相当于我们的服务器受到攻击了呢

我们的处理方法是:

1.在子进程中运行该程序

2.捕获子进程发送到标准输出的一切

3.返回给发起请求的客户端

完整的cgi协议比这更丰富,它允许URL中存在参数,服务器会将他们传入正在运行的程序(似乎这就是搜索引擎的架构哇,在url中添加参数然后丢到引擎里去然后返回一个html),

但这并不影响系统的整体架构。

于是我们的源码如下:

import sys, os, BaseHTTPServer

#-------------------------------------------------------------------------------

class ServerException(Exception):
    ‘‘‘For internal error reporting.‘‘‘
    pass

#-------------------------------------------------------------------------------

class base_case(object):
    ‘‘‘Parent for case handlers.‘‘‘

    def handle_file(self, handler, full_path):
        try:
            with open(full_path, ‘rb‘) as reader:
                content = reader.read()
            handler.send_content(content)
        except IOError as msg:
            msg = "‘{0}‘ cannot be read: {1}".format(full_path, msg)
            handler.handle_error(msg)

    def index_path(self, handler):
        return os.path.join(handler.full_path, ‘index.html‘)

    def test(self, handler):
        assert False, ‘Not implemented.‘

    def act(self, handler):
        assert False, ‘Not implemented.‘

#-------------------------------------------------------------------------------

class case_no_file(base_case):
    ‘‘‘File or directory does not exist.‘‘‘

    def test(self, handler):
        return not os.path.exists(handler.full_path)

    def act(self, handler):
        raise ServerException("‘{0}‘ not found".format(handler.path))

#-------------------------------------------------------------------------------

class case_cgi_file(base_case):
    ‘‘‘Something runnable.‘‘‘

    def run_cgi(self, handler):
        cmd = "python " + handler.full_path
        child_stdin, child_stdout = os.popen2(cmd)
        child_stdin.close()
        data = child_stdout.read()
        child_stdout.close()
        handler.send_content(data)

    def test(self, handler):
        return os.path.isfile(handler.full_path) and                handler.full_path.endswith(‘.py‘)

    def act(self, handler):
        self.run_cgi(handler)

#-------------------------------------------------------------------------------

class case_existing_file(base_case):
    ‘‘‘File exists.‘‘‘

    def test(self, handler):
        return os.path.isfile(handler.full_path)

    def act(self, handler):
        self.handle_file(handler, handler.full_path)

#-------------------------------------------------------------------------------

class case_directory_index_file(base_case):
    ‘‘‘Serve index.html page for a directory.‘‘‘

    def test(self, handler):
        return os.path.isdir(handler.full_path) and                os.path.isfile(self.index_path(handler))

    def act(self, handler):
        self.handle_file(handler, self.index_path(handler))

#-------------------------------------------------------------------------------

class case_directory_no_index_file(base_case):
    ‘‘‘Serve listing for a directory without an index.html page.‘‘‘

    # How to display a directory listing.
    Listing_Page = ‘‘‘        <html>
        <body>
        <ul>
        {0}
        </ul>
        </body>
        </html>
        ‘‘‘

    def list_dir(self, handler, full_path):
        try:
            entries = os.listdir(full_path)
            bullets = [‘<li>{0}</li>‘.format(e) for e in entries if not e.startswith(‘.‘)]
            page = self.Listing_Page.format(‘\n‘.join(bullets))
            handler.send_content(page)
        except OSError as msg:
            msg = "‘{0}‘ cannot be listed: {1}".format(self.path, msg)
            handler.handle_error(msg)

    def test(self, handler):
        return os.path.isdir(handler.full_path) and                not os.path.isfile(self.index_path(handler))

    def act(self, handler):
        self.list_dir(handler, handler.full_path)

#-------------------------------------------------------------------------------

class case_always_fail(base_case):
    ‘‘‘Base case if nothing else worked.‘‘‘

    def test(self, handler):
        return True

    def act(self, handler):
        raise ServerException("Unknown object ‘{0}‘".format(handler.path))

#-------------------------------------------------------------------------------

class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    ‘‘‘
    If the requested path maps to a file, that file is served.
    If anything goes wrong, an error page is constructed.
    ‘‘‘

    Cases = [case_no_file(),
             case_cgi_file(),
             case_existing_file(),
             case_directory_index_file(),
             case_directory_no_index_file(),
             case_always_fail()]

    # How to display an error.
    Error_Page = """        <html>
        <body>
        <h1>Error accessing {path}</h1>
        <p>{msg}</p>
        </body>
        </html>
        """

    # Classify and handle request.
    def do_GET(self):
        try:

            # Figure out what exactly is being requested.
            self.full_path = os.getcwd() + self.path

            # Figure out how to handle it.
            for case in self.Cases:
                if case.test(self):
                    case.act(self)
                    break

        # Handle errors.
        except Exception as msg:
            self.handle_error(msg)

    # Handle unknown objects.
    def handle_error(self, msg):
        content = self.Error_Page.format(path=self.path, msg=msg)
        self.send_content(content, 404)

    # Send actual content.
    def send_content(self, content, status=200):
        self.send_response(status)
        self.send_header("Content-type", "text/html")
        self.send_header("Content-Length", str(len(content)))
        self.end_headers()
        self.wfile.write(content)

#-------------------------------------------------------------------------------

if __name__ == ‘__main__‘:
    serverAddress = (‘‘, 8080)
    server = BaseHTTPServer.HTTPServer(serverAddress, RequestHandler)
    server.serve_forever()

为我们所有的事件创建一个父类,当且仅当方法在多个处理器间共享时将他们移入父类中,然后分别重载我们的方法就可以啦

时间: 2024-07-30 10:05:39

python web 服务器学习笔记(四)的相关文章

python web服务器学习笔记(五) 并发尝试之popen原理探究

使用popen新开进程能实现并发吗?像这样的cgi处理程序 def run_cgi(self,handler): cmd = "python" +handler.full_path child_stdin,child_stdout=os.popen2(cmd) child_stdin.close() data=child_stdout.read() child_stdout.close() handler.send_content(data) 我让它跑 for i in range(1

WEB前端学习笔记 四

接上一篇,web学习笔记 四,在此感谢您对此篇笔记的认可,但转发时请注明文章出自网知博学. 2.0  html的语法格式 html的标签要写在尖括号中 :<> 在在英文输入法状态下,按住shift键然后再按它左侧的尖括号就可了, 先学习一个简单的h1标签,是个标题标签,在html中这样写: <h1>我在h1标签中,我就是标题</h1> 那么h1标签中所包裹的文字,就标记成标题了.通过浏览器的解析后在页面上显示出来的效果就是字体加粗,加黑,和word中的标题性质一样! 大

python web框架学习笔记

一.web框架本质 1.基于socket,自己处理请求 #!/usr/bin/env python3 #coding:utf8 import socket def handle_request(client): #接收请求 buf = client.recv(1024) print(buf) #返回信息 client.send(bytes('<h1>welcome liuyao webserver</h1>','utf8')) def main(): #创建sock对象 sock

Kestrel Web 服务器学习笔记

前言: ASP.NET Core 已经不是啥新鲜的东西,很多新启的项目都会首选 Core 做开发: 而 Kestrel 可以说是微软推出的唯一真正实现跨平台的 Web 服务器了: Kestrel 利用一个名为 KestrelEngine 的网络引擎实现对请求的监听.接收和响应: Ketrel 之所以具有跨平台的特质,源于 KestrelEngine 是在一个名为 libuv 的跨平台网络库上开发的: Kestrel is a cross-platform web server for ASP.N

JSP实现数据保存(web基础学习笔记四)

session对象: //服务端设置Session属性 session.setAttribute("user", username); //客户端接收Session Object obj = session.getAttribute("user"); //判断是否为空,不是空就输出 if(obj==null){ //如果为空就提示用户登录 %> <%}else{ //不为空就输出用户名,和欢迎信息 out.println("欢迎您"+

python简易web服务器学习笔记(三)

import sys, os, BaseHTTPServer #------------------------------------------------------------------------------- class ServerException(Exception): '''For internal error reporting.''' pass #--------------------------------------------------------------

python简易web服务器学习笔记(二)

import BaseHTTPServer #------------------------------------------------------------------------------- class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): '''Respond to HTTP requests with info about the request.''' # Template for page to sen

Django Web开发学习笔记(5)

第五部分 Model 层 创建一个app工程.app和project的区别引用DjangoBook的说法是: 一个project包含很多个Django app以及对它们的配置. 技术上,project的作用是提供配置文件,比方说哪里定义数据库连接信息, 安装的app列表, TEMPLATE_DIRS ,等等. 一个app是一套Django功能的集合,通常包括模型和视图,按Python的包结构的方式存在. 例如,Django本身内建有一些app,例如注释系统和自动管理界面. app的一个关键点是它

Django Web开发学习笔记(4)

第四章 模板篇 上一章的内容,我们将HTML的代码和Python代码都混合在了在view.py的文件下.但是这样做的坏处无疑是明显的,引用DjangoBook的说法: 对页面设计进行的任何改变都必须对 Python 代码进行相应的修改. 站点设计的修改往往比底层 Python 代码的修改要频繁得多,因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多. Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门