面向对象封装的web服务器

import socket
import re
import os
import sys

# 由于前面太繁琐,可以用类封装一下,也可以分几个模块
class HttpServer(object):

    def __init__(self,port):
        # 1、服务器创建负责监听的socket
        self.socket_watch = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2、设置地址重用
        self.socket_watch.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 3、绑定监听的端口
        self.socket_watch.bind((‘‘, port))
        # 4、设置监听队列
        self.socket_watch.listen(128)

    def handle_client(self,socket_con):
        """
         接收来自客户端的请求,并接收请求报文,解析,返回
        """
        # 1、服务器接收客户端的请求报文
        request = socket_con.recv(4096).decode()

        # 2、截取请求报文,获取请求行
        request_lines = request.split("\r\n")
        # 3、获取请求行
        request_line = request_lines[0]
        # GET /a/ab/c.html HTTP/1.1
        # 通过正则表达式 匹配出请求行中请求资源路径
        res = re.match(r"\w+\s+(\S+)",request_line)
        # 获取资源路径
        path = res.group(1)
        # 将资源路径和我的web文件夹的绝对路径拼接(自己填写)
        path ="# 本地绝对路径" + path
        # 在判断是文件还是文件夹之前,首先要判断你这个路径在服务器中是否存在
        if not os.path.exists(path):
            response_line = ‘HTTP/1.1 404 Not Found\r\n‘
            response_head = ‘Server:skylark 2.0\r\n‘
            response_head += ‘Content-type:text/html;charset=utf-8\r\n‘
            response_body = ‘你请求‘+ path +‘不存在‘
            response = response_line + response_head + ‘\r\n‘ +response_body
            socket_con.send(response.encode())
            socket_con.close()
            return
        else:
            # 判断用户请求的是文件还是文件夹
             if os.path.isfile(path):
                 # 如果文件存在 读取页面数据,然后返回
                response_line = "HTTP/1.1 200 OK\r\n"
                response_head = "Server:skylark 2.0\r\n"
                # 注意请求图片需要使用"rb"的方式进行读取
                file = open(path,"rb")
                # response_body 是二进制所以不用再次编码
                response_body = file.read()
                response = response_line.encode() + response_head.encode() +"\r\n".encode() +response_body
                socket_con.send(response)
                socket_con.close()
                return
             else:
                if path.endswith("/"):
                    # 例如 www.baidu.com/images
                    # 用户请求的文件夹
                    # 1、判断该文件夹下是否有默认的文件,如果有,则返回,如果没有
                    # index.html default.html
                    default_document = False
                    # 如果允许你访问我目录下的默认文档
                    if default_document:
                        # 判断用户访问的文件夹下是否有index.html 或者 default.html
                        if os.path.exists(path + ‘/index.html‘):
                            response_line = ‘HTTP/1.1 200 OK\r\n‘
                            response_head = ‘Server:skylark 2.0\r\n‘
                            file = open(path+‘/index.html‘, ‘rb‘)
                            response_body = file.read()
                            response = response_line.encode() + response_head.encode() +‘\r\n‘.encode()+response_body
                            socket_con.send(response)
                            socket_con.close()
                            return
                        elif os.path.exists(path + ‘/default.html‘):
                            response_line = ‘HTTP/1.1 200 OK\r\n‘
                            response_head = ‘Server:skylark 2.0\r\n‘
                            file = open(path + ‘/default.html‘, ‘rb‘)
                            response_body = file.read()
                            response = response_line.encode() + response_head.encode() + ‘\r\n‘.encode() + response_body
                            socket_con.send(response)
                            socket_con.close()
                            return
                        else:
                            # 访问的目录下,既没有index.html 也没有default.html
                            response_line = ‘HTTP/1.1 404 Not Found\r\n‘
                            response_head = ‘Server:skylark 2.0\r\n‘
                            response_head += ‘Content-Type:text/html;charset=utf-8\r\n‘
                            response_body = ‘index.html 或者 default.html 不存在‘
                            response = response_line +response_head +‘\r\n‘ +response_body
                            socket_con.send(response.encode())
                            socket_con.close()
                        # 2、判断服务器是否开启了目录浏览
                    else:
                        # 判断你是否开启了目录浏览
                        dir_browsing = True
                        if dir_browsing:
                            # 把用户请求的文件夹中所有的文件和文件夹以目录的形式返回到页面中
                            # 获取用户请求的文件夹
                            list_names = os.listdir(path)
                            response_line = ‘HTTP/1.1 200 OK\r\n‘
                            response_head = ‘Server:skylark 2.0\r\n‘
                            # 动态的拼接页面,将目录中的文件或者文件夹的名称以HTML页面的方式返回给浏览器
                            response_body = ‘<html><head><body><ul>‘
                            for item in  list_names:
                                response_body +="<li><a href = ‘#‘>"+item+"</a></li>"
                            response_body+=‘</ul></body></head></html>‘
                            response =response_line + response_head +‘\r\n‘ +response_body
                            socket_con.send(response.encode())
                            socket_con.close()
                            return

                else:
                    # 用户请求的路径没有斜线
                    # 重定向到+斜线的目录下
                    response_line = ‘HTTP/1.1 302 Found\r\n‘
                    response_head = ‘Server:skylark 2.0\r\n‘
                    response_body = ‘redirect‘+ path +‘/‘
                    response = response_line +response_head +‘\r\n‘ +response_body
                    socket_con.send(response.encode())
                    socket_con.close()

    def run_server(self):
        # 5、通过循环,不停的接收来自客户端的连接请求
        while True:
            socket_con, con_adds = self.socket_watch.accept()
            # 注意将con_adds转成字符串
            print(‘客户端:%s连接成功!!!‘ % str(con_adds))
            # 接收来自客户端的请求,并接收请求报文,解析,返回
            self.handle_client(socket_con)

def main():
    # sys.argv方法的用法如下:
    # 在终端输入 python3 面向对象封装的web服务器.py 8888
    # 在使用解释器执行任意py文件的时候,可以传入不止一个参数,会以字符串的形式用列表保存起来
    # 但是列表的第一个参数[0]位是它自己。所以传入的参数是从[1]第二位开始的
    # 所以在上面输入8888以后,调取这个列表的[1]下标就会传入这个8888作为进到下面的代码
    # 再转换一下类型为int就相当于用户指定端口了
    port = int(sys.argv[1])
    http_server = HttpServer(port)
    http_server.run_server()

if __name__ == ‘__main__‘:
    main()

  

原文地址:https://www.cnblogs.com/wf-skylark/p/9027154.html

时间: 2024-10-05 05:06:49

面向对象封装的web服务器的相关文章

Linux下Web服务器开发

学习提示: 1. 在"桌面环境"中动手练习,若环境不流畅可选择WebIDE或字符界面. 2. 在教程下方"课程问答"中提出问题,或"共享桌面"寻求远程帮助. 3. 在教程下方"实验报告"中完成作业,记录心得.公开报告可以获得大家点评. 4. 在"我的代码库"中用GIT提交你的实验代码. Web服务器 The way to learn a programming language is to write pr

反向Ajax,第3部分:Web服务器和Socket.IO

英文原文:Reverse Ajax, Part 3: Web servers and Socket.IO 前言 时至今日,用户期待的是可通过web访问快速.动态的应用.这一文章系列展示了如何使用反向Ajax(Reverse Ajax)技术来开发事件驱动的web应用.系列的第1部分介绍了反向Ajax.轮询(polling).流(streaming).Comet和长轮询(long polling).你已经了解了Comet是如何使用HTTP长轮询的,这是可靠地实现反向Ajax的最好方式,因为现有的所有

外网主机访问虚拟机下的web服务器(NAT端口转发)

主机:系统win7,ip地址172.18.186.210 虚拟机:VMware Workstation 7,虚拟机下安装了Centos操作系统,ip地址是192.168.202.128,部署了LAMP,成为一个web服务器 网络环境:校园网(有认证服务器,需要账号认证才能上网),虚拟机采用NAT的方式联网 在校园网的环境下,可以把校园网内的其他主机看成是外网的主机.其实,虚拟机采用NAT联网的方式,可以让我们联想到计算机网络的相关知识,可以把我们的主机看成是一部路由器,然后虚拟机就是处在一个局域

关于Web服务器的认识

马上就要毕业了,也要开始找工作了,大学写了这么多代码了,却没有好好总结一下常用的概念很是遗憾额,就通过这篇博客记录一下我最常用的一些知识好了. 说到Web服务器,有很多文章都介绍的很好,之前看到一篇非常不错的,对我帮助很大,可惜现在找不到原文了,看到博客园有人转载,我就在这里也记一下好了,在此非常感谢作者的分析,受益匪浅. 那么在说Web服务器之前,先说说线程.进程.以及并发连接数. 1.进程与线程 进程是具有一定独立功能的程序,关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一

自己动手模拟开发一个简单的Web服务器

开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此事要躬行”,于是我们自己模拟一个简单的Web服务器来体会一下. 一.请求-处理-响应模型 1.1 基本过程介绍 每一个HTTP请求都会经历三个步凑:请求-处理-响应:每当我们在浏览器中输入一个URL时都会被封装为一个HTTP请求报文发送到Web服务器,而Web服务器则接收并解析HTTP请求报文,然后针对请求进行处理(返回指定的HTML页面

Socket 初识 用Socket建立一个简易Web服务器

摘自<Asp.Net 本质论>作者:郝冠军 //在.Net中.system.Net命名空间提供了网络编程的大多数数据据类型以及常用操作,其中常用的类型如下:/*IPAddress 类表示一个IP地址* IPEndPoint类用来表示一个IP地址和一个端口号的组合,成为网络的端点.* System.Net.Sockets命名空间中提供了基于Socked编程的数据类型.* Socket类封装了Socked的操作.* 常见的操作:* Listen:设置基于连接通信的Socket进入监听状态,并设置等

Kestrel Web 服务器学习笔记

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

apache web服务器与防盗链的设置

一.安装apache2.4.23 新版本的httpd-2.4新增以下特性: 新增模块: mod_proxy_fcgi(可提供fcgi代理) mod_ratelimit(限制用户带宽) mod_request(请求模块,对请求做过滤) mod_remoteip(匹配客户端的IP地址) 对于基于IP的访问控制做了修改,不再支持allow,deny,order机制,而是统一使用require进行 还新增以下几条新特性: 1.MPM支持在运行时装载;不过要开启这种特性,在编译安装要启用这三种功能: --

Tinywebserver:一个简易的web服务器

这是学习网络编程后写的一个练手的小程序,可以帮助复习I/O模型,epoll使用,线程池,HTTP协议等内容. 程序代码是基于<Linux高性能服务器编程>一书编写的. 首先回顾程序中的核心内容和主要问题,最后给出相关代码. 0. 功能和I/O模型 实现简易的HTTP服务端,现仅支持GET方法,通过浏览器访问可以返回相应内容. I/O模型采用Reactor(I/O复用 + 非阻塞I/O) + 线程池. 使用epoll事件循环用作事件通知,如果listenfd上可读,则调用accept,把新建的f