Python实现简单的HttpServer服务器示例


Posted in Python onSeptember 25, 2017

要写一个类似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 相关文章推荐
Python获取二维矩阵每列最大值的方法
Apr 03 Python
django rest framework 数据的查找、过滤、排序的示例
Jun 25 Python
python爬取百度贴吧前1000页内容(requests库面向对象思想实现)
Aug 10 Python
Django认证系统实现的web页面实现代码
Aug 12 Python
Python数据可视化:顶级绘图库plotly详解
Dec 07 Python
Python pygame绘制文字制作滚动文字过程解析
Dec 12 Python
python获取栅格点和面值的实现
Mar 10 Python
解决更改AUTH_USER_MODEL后出现的问题
May 14 Python
Docker如何部署Python项目的实现详解
Oct 26 Python
python实现视频压缩功能
Dec 18 Python
Pytorch模型迁移和迁移学习,导入部分模型参数的操作
Mar 03 Python
Python正则表达式中flags参数的实例详解
Apr 01 Python
Python使用正则表达式过滤或替换HTML标签的方法详解
Sep 25 #Python
Python实现的破解字符串找茬游戏算法示例
Sep 25 #Python
Python实现破解猜数游戏算法示例
Sep 25 #Python
Python基于identicon库创建类似Github上用的头像功能
Sep 25 #Python
python3使用requests模块爬取页面内容的实战演练
Sep 25 #Python
python中通过预先编译正则表达式提高效率
Sep 25 #Python
python之Character string(实例讲解)
Sep 25 #Python
You might like
多文件上载系统完整版
2006/10/09 PHP
PHP 引用是个坏习惯
2010/03/12 PHP
PHP 小心urldecode引发的SQL注入漏洞
2011/10/27 PHP
php微信开发之上传临时素材
2016/06/24 PHP
PHP自定义多进制的方法
2016/11/03 PHP
iframe自适应宽度、高度 ie6 7 8,firefox 3.86下测试通过
2010/07/29 Javascript
仅Firefox中链接A无法实现模拟点击以触发其默认行为
2011/07/31 Javascript
解析dom中的children对象数组元素firstChild,lastChild的使用
2013/07/10 Javascript
使用jQuery异步加载 JavaScript脚本解决方案
2014/04/20 Javascript
Node.js中使用Log.io在浏览器中实时监控日志(等同tail -f命令)
2014/09/17 Javascript
JavaScript中toString()方法的使用详解
2015/06/05 Javascript
两种JavaScript的AES加密方式(可与Java相互加解密)
2016/08/02 Javascript
jQuery轻松实现无缝轮播效果
2017/03/22 jQuery
javascript少儿编程关于返回值的函数内容
2018/05/27 Javascript
小程序扫描普通链接二维码跳转小程序指定界面方法
2019/05/07 Javascript
详解基于Vue的支持数据双向绑定的select组件
2019/09/02 Javascript
node解析修改nginx配置文件操作实例分析
2019/11/06 Javascript
Vue实例的对象参数options的几个常用选项详解
2019/11/08 Javascript
Vue 图片压缩并上传至服务器功能
2020/01/15 Javascript
JS+HTML5本地存储Localstorage实现注册登录及验证功能示例
2020/02/10 Javascript
详解ES6实现类的私有变量的几种写法
2021/02/10 Javascript
[16:43]Heroes19_剃刀(完美)
2014/10/31 DOTA
[14:56]教你分分钟做大人:巫医
2014/10/30 DOTA
python daemon守护进程实现
2016/08/27 Python
TensorFlow模型保存和提取的方法
2018/03/08 Python
Python比较2个时间大小的实现方法
2018/04/10 Python
python GUI框架pyqt5 对图片进行流式布局的方法(瀑布流flowlayout)
2020/03/12 Python
Python读写压缩文件的方法
2020/07/30 Python
通过实例简单了解python yield使用方法
2020/08/06 Python
信息工程学院毕业生推荐信
2013/11/05 职场文书
党员思想汇报范文
2013/12/30 职场文书
大学生职业生涯规划书范文
2014/01/04 职场文书
人事专员岗位职责说明书
2014/07/30 职场文书
2014年财政所工作总结
2014/11/22 职场文书
构建和谐校园倡议书
2015/01/19 职场文书
导游词之苏州盘门景区
2019/11/12 职场文书