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()

  

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

  1. Node.js学习笔记(五) --- 使用Node.js搭建Web服务器

    1. Node.js 创建的第一个应用 1.引入http模块 var http = require("http"); 2. 创建服务器接下来我们使用 http.createServ ...

  2. 01-静态web服务器(Python)-面向对象的对比

    普通写法,静态web服务器: 先创建TCP服务器套接字,然后等待客户端(这里是浏览器)请求连接. 客户端发起请求,用线程来处理连接的建立,这样可以实现多任务(也就是并发) 连接后根据请求发送指定页面 ...

  3. 利用Python实现对Web服务器的目录探测

    今天是一篇提升技能的干货分享,操作性较强,适用于中级水平的小伙伴,文章阅读用时约3分钟. PART 1/Python Python是一种解释型.面向对象.动态数据类型的高级程序设计语言. Python ...

  4. 利用 python 实现对web服务器的目录探测

    一.pythonPython是一种解释型.面向对象.动态数据类型的高级程序设计语言.python 是一门简单易学的语言,并且功能强大也很灵活,在渗透测试中的应用广泛,让我们一起打造属于自己的渗透测试工 ...

  5. JavaSE 手写 Web 服务器(一)

    原文地址:JavaSE 手写 Web 服务器(一) 博客地址:http://www.extlight.com 一.背景 某日,在 Java 技术群中看到网友讨论 tomcat 容器相关内容,然后想到自 ...

  6. 一不小心写了个WEB服务器

    开场 Web服务器是啥玩意? 是那个托管了我的网站的机器么? No,虽然那个也是服务器,但是我们今天要说的Web服务器主要是指像IIS这样一类的,用于处理request并返回response的工具,没 ...

  7. 自己实现一个简易web服务器

    一个web服务器是网络应用中最基础的环节. 构建需要理解三个内容: 1.http协议 2.socket类 3.服务端实现原理 1.1 HTTP http请求 一般一个http请求包括以下三个部分: 1 ...

  8. 关于Web服务器的认识

    马上就要毕业了,也要开始找工作了,大学写了这么多代码了,却没有好好总结一下常用的概念很是遗憾额,就通过这篇博客记录一下我最常用的一些知识好了. 说到Web服务器,有很多文章都介绍的很好,之前看到一篇非 ...

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

    开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此事要躬行”,于是我们自己模拟一个简单的W ...

随机推荐

  1. SUN巡检命令

    # hostname (主机名)# hostid# uname -X# uname -a # w (进程)# who# last# ps -eaf# /usr/ucb/ps -aux# prstat ...

  2. Tomcat启动时报错:“ Error starting static Resources”问题解决

    部署测试环境的时候,需要用到Tomcat.故在Linux上部署了Tomcat,并将开发提供的工程包部署到Tomcat的webapps目录下,启动Tomcat,部署成功.第二天修改工程配置文件时,发现w ...

  3. Golang笔记(一)简洁的语言风格

    Golang笔记(一)简洁的语言风格 概述 Golang继承了很多C语言的风格,寡人使用了十几年C语言,切换到Golang时上手很快,并且随着深入的使用,越来越喜欢这门语言.Golang最直观的感受是 ...

  4. Postman工具——下载与安装(转)

    https://blog.csdn.net/water_0815/article/details/53263643 今天给大家分享一款工具,好的工具能够让开发更高效,有时能成倍地提高.接下来会分几篇来 ...

  5. apache部署多域名,同个ip部署多个网站

    写个总结笔记,让以后的自己知道怎么部署. 首先apache的版本是2.4.7,然后系统是Ubuntu 14.04.1 LTS.(因为好像配置文件和目录有差异) 首先进到apache2目录下, 我们要探 ...

  6. Conferences

    中国学术会议在线 :http://www.meeting.edu.cn 中国会议网: http://www.chinameeting.com 香山科学会议:http://www.xssc.ac.cn/ ...

  7. Android中快速实现自定义字体!

    前言:我们都知道,Android中默认的字体是黑体,而大多数app也都是使用的这种字体,但我们发现,大多数app中,个别地方字体非常好看,例如app的标题栏,菜单栏等地方,那他们是怎么做到的呢?有两种 ...

  8. 夜色的 cocos2d-x 开发笔记 00

    第一次写博客,本人还是大二学生,纯新手,无论是文章的技术性,还是参考性,都不高,但却是根据我的经历,开发过的真实过程,对自己记载一些备忘的笔记,更希望也能帮到一些人. 本人用的win7 + vs201 ...

  9. 动软代码生成器,主子表增加的时候子表的parentID无法插入问题解决方案

    StringBuilder strSql=new StringBuilder(); strSql.Append("insert into HT_XunJiaMain("); str ...

  10. SQL-常用数据类型

    整数除了 INT 外,还有 TINYINT.SMALLINT.MEDIUMINT.BIGINT. CHAR 和 VARCHAR 的区别: CHAR 的长度是固定的,而 VARCHAR 的长度是可以变化 ...