要写一个类似tomcat的简易服务器,首先需弄清楚这几点:

1. 客户端(Client)和服务端(Server)的角色及作用

角色A向角色B请求数据,这时可以把A视为客户端,B视为服务端。客户端的主要职责是发送请求和接收服务端根据自己发送的请求返回的请求信息,而服务端的主要职责是接收请求和返回请求数据。

2. 浏览器是什么及工作原理

我们常说B/S,C/S架构,所谓的B/S指browser/server,C/S指Client/Server,B/S架构其实就是应用于浏览器的程序,只要最后在浏览器上展现的都是 B/S架构,而非在浏览器上展现的都是C/S架构,如常见的英雄联盟游戏。但是本质上只有C/S架构,因为浏览器是一种特殊的客户端。

浏览器的特殊之处是有一下三大引擎:

DOM解析引擎:即浏览器可以解析HTML

样式解析引擎:即浏览器可以解析CSS

脚本解析引擎:即浏览器可以解析JAVASCRIPT

3. Socket

上面提到的客户端服务端,他们之间是怎样实现连接及数据传递的,这就是Socket,每一门编程语言都有Socket编程,Socket的作用就是提供了网络通信的能力

4. HTTP协议及HTTP与TCP/TP的区别

客户端和服务端通过Socket实现了网络通信的能力,可以实现数据传递。而协议是规范数据传输,也就是说客户端和服务端之间传输数据要按照一定得规范和标准传输,不能瞎传。

TCP/IP(Transmission Control Protocol/Internet Protocol):传输控制协议/网间协议

HTTP(HyperText Transfer Protocol):超文本传输协议。

TCP/TP的区别:

做一个形象的比喻,TCP/TP是马路,HTTP则是马路上的汽车,所以HTTP一定是在TCP/TP的基础上的。

HTTP主要是应用在web程序上,设计之初就是为了提供一种发布和接收HTML页面的方法,这样说可能很抽象很难理解。具体的说当我们去访问一个网站时,只需要拿到基于这个网站的内容(比如html,css,JavaScript)。但我们抓取浏览器接收到的资源包(可以用Fiddler工具)发现除了网页需要的实体内容还有一些下面信息:

HTTP/1.1 200 OK

Cache-Control: private

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

Content-Encoding: gzip

Vary: Accept-Encoding

Server: Microsoft-IIS/7.5

X-AspNet-Version: 4.0.30319

X-Powered-By: ASP.NET

Date: Tue, 24 Jan 2017 03:25:23 GMT

Connection: close

Content-Length: 661

这就是http协议规范,比如Content-Type就是说传输的时候文件的格式,Content-Encoding规定了编码格式。不止以上这些,非常多,关于这些参数含义这里就不去一一介绍

5. URL的含义

URL(统一资源定位符),就是我们常说的网址,直接来解析一个URL来说明他

http://198.2.17.25:8080/webapp/index.html

这个含义是找到IP为198.2.17.25的服务器下目录为webapp的index.html

但是我们常看到的是这样的URL:

http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx

其实这个和上面的一样,不过这里存在一个域名解析,可以将goodcandle.cnblogs.com解析成对应的IP地址

弄清楚以上五点之后开始来写代码

webServer.py

import socket
import sys
import getFileContent
#声明一个将要绑定的IP和端口,这里是用本地地址
server_address = ('localhost', 8080)
class WebServer():
def run(self):
print >>sys.stderr, 'starting up on %s port %s' % server_address
#实例化一个Socket
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#绑定IP和端口
sock.bind(server_address)
#设置监听
sock.listen(1)
#这里首先给个死循环,其实这里是需要多线程的,再后续版本将会实现
while True:
#接受客户端的请求并得到请求信息和请求的端口信息
connection, client_address = sock.accept()
print >>sys.stderr, 'waiting for a connection'
try:
#获取请求信息
data = connection.recv(1024)
if data:
#发送请求信息
connection.sendall(getFileContent.getHtmlFile(data))
finally:
connection.close() if __name__ == '__main__':
server=WebServer()
server.run()

webServer.py很清晰简洁,connection.sendall()服务端返回信息给浏览器,但是发送的数据必须遵循HTTP协议规范

getFileContent.py是对发送的数据进行HTTP协议规范处理

import sys
import os #得到要发送的数据信息
def getHtmlFile(data):
msgSendtoClient=""
requestType=data[0:data.find("/")].rstrip()
#判断是GET请求还是POST请求
if requestType=="GET":
msgSendtoClient=responseGetRequest(data,msgSendtoClient)
if requestType=="POST":
msgSendtoClient=responsePostRequest(data,msgSendtoClient)
return msgSendtoClient #打开文件,这里不直接写,二是去取要发送的文件再写
def getFile(msgSendtoClient,file):
for line in file:
msgSendtoClient+=line
return msgSendtoClient #筛选出请求的一个方法
def getMidStr(data,startStr,endStr):
startIndex = data.index(startStr)
if startIndex>=0:
startIndex += len(startStr)
endIndex = data.index(endStr)
return data[startIndex:endIndex] #获取要发送数据的大小,根据HTTP协议规范,要提前指定发送的实体内容的大小
def getFileSize(fileobject):
fileobject.seek(0,2)
size = fileobject.tell()
return size #设置编码格式和文件类型
def setParaAndContext(msgSendtoClient,type,file,openFileType):
msgSendtoClient+="Content-Type: "+type+";charset=utf-8"
msgSendtoClient+="Content-Length: "+str(getFileSize(open(file,"r")))+"\n"+"\n"
htmlFile=open(file,openFileType)
msgSendtoClient=getFile(msgSendtoClient,htmlFile)
return msgSendtoClient #GET请求的返回数据
def responseGetRequest(data,msgSendtoClient):
return responseRequest(getMidStr(data,'GET /','HTTP/1.1'),msgSendtoClient) #POST请求的返回数据
def responsePostRequest(data,msgSendtoClient):
return responseRequest(getMidStr(data,'POST /','HTTP/1.1'),msgSendtoClient) #请求返回数据
def responseRequest(getRequestPath,msgSendtoClient):
headFile=open("head.txt","r")
msgSendtoClient=getFile(msgSendtoClient,headFile)
if getRequestPath==" ":
msgSendtoClient=setParaAndContext(msgSendtoClient,"text/html","index.html","r")
else:
rootPath=getRequestPath
if os.path.exists(rootPath) and os.path.isfile(rootPath):
if ".html" in rootPath:
msgSendtoClient=setParaAndContext(msgSendtoClient,"text/html",rootPath,"r")
if ".css" in rootPath:
msgSendtoClient=setParaAndContext(msgSendtoClient,"text/css",rootPath,"r")
if ".js" in rootPath:
msgSendtoClient=setParaAndContext(msgSendtoClient,"application/x-javascript",rootPath,"r")
if ".gif" in rootPath:
msgSendtoClient=setParaAndContext(msgSendtoClient,"image/gif",rootPath,"rb")
if ".doc" in rootPath:
msgSendtoClient=setParaAndContext(msgSendtoClient,"application/msword",rootPath,"rb")
if ".mp4" in rootPath:
msgSendtoClient=setParaAndContext(msgSendtoClient,"video/mpeg4",rootPath,"rb")
else:
msgSendtoClient=setParaAndContext(msgSendtoClient,"application/x-javascript","file.js","r")
return msgSendtoClient

Github源码下载:https://github.com/Jiashengp/Python_httpServer

Python实现简单的HttpServer的更多相关文章

  1. linux下用python搭建简单的httpServer

    1.服务器端:python -m SimpleHTTPServer 12000 python -m :  相当于import,当做模块来启动; 后面的12000代表的是端口 使用浏览器打开如下: 2. ...

  2. Python 实现简单的 Web

    简单的学了下Python, 然后用Python实现简单的Web. 因为正在学习计算机网络,所以通过编程来加强自己对于Http协议和Web服务器的理解,也理解下如何实现Web服务请求.响应.错误处理以及 ...

  3. python超简单的web服务器

    今天无意google时看见,心里突然想说,python做web服务器,用不用这么简单啊,看来是我大惊小怪了. web1.py   1 2 3 #!/usr/bin/python import Simp ...

  4. Go Socket实现简单的HttpServer

    在上篇博客中写到如何用Python实现一个类似tomcat的简单服务器,接下来用go语言去实现 1. Go本身自己封装实现了非常简单的httpServer package main import ( ...

  5. Python实现简单HTTP服务器

    Python实现简单HTTP服务器(一) 一.返回固定内容 复制代码 coding:utf-8 import socket from multiprocessing import Process de ...

  6. 用 python实现简单EXCEL数据统计

    任务: 用python时间简单的统计任务-统计男性和女性分别有多少人. 用到的物料:xlrd 它的作用-读取excel表数据 代码: import xlrd workbook = xlrd.open_ ...

  7. python开启简单webserver

    python开启简单webserver linux下面使用 python -m SimpleHTTPServer 8000 windows下面使用上面的命令会报错,Python.Exe: No Mod ...

  8. Python开发简单爬虫 - 慕课网

    课程链接:Python开发简单爬虫 环境搭建: Eclipse+PyDev配置搭建Python开发环境 Python入门基础教程 用Eclipse编写Python程序   课程目录 第1章 课程介绍 ...

  9. python使用简单http协议来传送文件

    python使用简单http协议来传送文件!在ubuntu环境下,局域网内可以使用nc来传送文件,也可以使用基于Http协议的方式来下载文件我们可以使用python -m SimpleHTTPServ ...

随机推荐

  1. docker基础维护命令

    docker images显示当前存在的images docker ps,显示当前的container docker rm containerId 删除指定的container(需要先停止,才能删除) ...

  2. Asp.Net core 视图组件ViewComponent

    视图组件 ViewComponent 最近用了一下视图组件,还挺方便的,如果遇到公共的部分,可以抽出来,写成视图组件,方便调用 先上图看一下效果:比如首页的4个画红框的地方是4个模块,有些地方可能要重 ...

  3. VueRouter和Vue生命周期(钩子函数)

    一.vue-router路由 1.介绍 vue-router是Vue的路由系统,用于定位资源的,在页面不刷新的情况下切换页面内容.类似于a标签,实际上在页面上展示出来的也是a标签,是锚点.router ...

  4. CentOS 7安装MongoDB

    1 下载安装包 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.2.4.tgz 2 解压 .tgz 3 将解压包 ...

  5. 10.3 Vue 路由系统

     Vue 路由系统  简单示例 main.js  import Vue from 'vue' import App from './App.vue' //https://router.vuejs.or ...

  6. 最大公约数和最小公倍数(Greatest Common Divisor and Least Common Multiple)

    定义: 最大公约数(英语:greatest common divisor,gcd).是数学词汇,指能够整除多个整数的最大正整数.而多个整数不能都为零.例如8和12的最大公因数为4. 最小公倍数是数论中 ...

  7. 打怪升级之路—Security+认证通关攻略(401还是501)

    我花了一个月才把题目过完一遍的(这一个月都上班,下班抽空做几页),这里面走了很多弯路,我把备考过程整理出来希望对大家有帮助. 我是在2019年1月完成的Security+考试,离安全牛课堂直播培训结束 ...

  8. 第十节:数据批注(DataAnnotationModel)和自定义验证(包括Model级别的验证)

    一. 简介 写完上一个章节MVC中的常用特性,迫不及待将该系列补全,该章节主要介绍数据批注(也叫:注解). 一听[数据批注],好高大上的名字,但仔细一看,它们其实是[System.ComponentM ...

  9. Scrapy 下载图片

    参考 : https://www.jianshu.com/p/6c8d2730d088 https://docs.scrapy.org/en/latest/topics/item-pipeline.h ...

  10. MD1——2 Corner

    基本句型 被分为 5 种全然因为[动词] 造成的. 那么补语 就是因为 动词被解释成“是”的时候所需要的一种补足. [补语 Complement 传统的毒瘤说法] 不完全不及物动词 不完全及物动词~~ ...