博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象封装的web服务器
阅读量:6589 次
发布时间:2019-06-24

本文共 6330 字,大约阅读时间需要 21 分钟。

import socketimport reimport osimport 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 = '
    ' for item in list_names: response_body +="
  • "+item+"
  • " response_body+='
' 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()

  

                                                                   -------  知识无价,汗水有情,如需搬运请注明出处,谢谢!

转载地址:http://vfuio.baihongyu.com/

你可能感兴趣的文章
Java8-Stream-No.12
查看>>
Java编译那些事儿【转】
查看>>
各种排序算法的总结
查看>>
[.net 面向对象程序设计进阶] (25) 团队开发利器(四)分布式版本控制系统Git——使用GitStack+TortoiseGit 图形界面搭建Git环境【转】...
查看>>
SpringBoot相关
查看>>
[LeetCode] Sudoku Solver 求解数独
查看>>
html5/haXe开发偶感
查看>>
js深入研究之神奇的匿名函数类生成方式
查看>>
The life cycle of a typical project 一个典型的项目生命周期
查看>>
推荐F#最近的一些资源
查看>>
Linux文件操作
查看>>
ylbtech-Recode(记录)-数据库设计
查看>>
运动目标跟踪与检测的源代码(CAMSHIFT 算法)
查看>>
PHP工厂模式的简单实现
查看>>
线程同步中异常情况的处理
查看>>
Orchard模块开发全接触3:分类的实现及内容呈现(Display)
查看>>
JQuery 自动触发事件
查看>>
ylbtech-LanguageSamples-CommandLine(命令行参数)
查看>>
Uptime And Monitoring Strategies For Cloud-Based E-Commerce Applications/Websites
查看>>
FPGA未来几年的发展趋势及发展机遇
查看>>