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编程之gui程序实现简单文件浏览器代码
Dec 08 Python
python Selenium实现付费音乐批量下载的实现方法
Jan 24 Python
PyCharm搭建Spark开发环境实现第一个pyspark程序
Jun 13 Python
一篇文章弄懂Python中所有数组数据类型
Jun 23 Python
Python使用Turtle库绘制一棵西兰花
Nov 23 Python
Python Des加密解密如何实现软件注册码机器码
Jan 08 Python
tensorflow实现对张量数据的切片操作方式
Jan 19 Python
Python2 与Python3的版本区别实例分析
Mar 30 Python
Python之变量类型和if判断方式
May 05 Python
Django 解决model 反向引用中的related_name问题
May 19 Python
教你一分钟在win10终端成功安装Pytorch的方法步骤
Jan 28 Python
Python趣味挑战之给幼儿园弟弟生成1000道算术题
May 28 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
php中的filesystem文件系统函数介绍及使用示例
2014/02/13 PHP
PHP将两个关联数组合并函数提高函数效率
2014/03/18 PHP
php校验表单检测字段是否为空的方法
2015/03/20 PHP
php resizeimage 部分jpg文件 生成缩略图失败的原因分析及解决办法
2016/03/23 PHP
功能强大的php分页函数
2016/07/20 PHP
实例分析10个PHP常见安全问题
2019/07/09 PHP
PHP7.3.10编译安装教程
2019/10/08 PHP
Javascript实现的分页函数
2006/12/22 Javascript
var与Javascript变量隐式声明
2009/09/17 Javascript
js处理表格对table进行修饰
2014/05/26 Javascript
基于jQuery实现二级下拉菜单效果
2016/02/01 Javascript
适用于javascript开发者的Processing.js入门教程
2016/02/24 Javascript
js 原型对象和原型链理解
2017/02/09 Javascript
$.browser.msie 为空或不是对象问题的多种解决方法
2017/03/19 Javascript
Layui数据表格之获取表格中所有的数据方法
2018/08/20 Javascript
Vue项目使用localStorage+Vuex保存用户登录信息
2019/05/27 Javascript
javascript面向对象三大特征之封装实例详解
2019/07/24 Javascript
layui使用label标签的方法
2019/09/14 Javascript
Vue中rem与postcss-pxtorem的应用详解
2019/11/20 Javascript
jQuery实现可编辑的表格
2019/12/11 jQuery
vue+iview框架实现左侧动态菜单功能的示例代码
2020/07/23 Javascript
vue使用vue-quill-editor富文本编辑器且将图片上传到服务器的功能
2021/01/13 Vue.js
快速入手Python字符编码
2016/08/03 Python
Python数据分析之双色球统计两个红和蓝球哪组合比例高的方法
2018/02/03 Python
python3获取文件中url内容并下载代码实例
2019/12/27 Python
python微信公众号开发简单流程实现
2020/03/09 Python
python设置表格边框的具体方法
2020/07/17 Python
Python如何读取、写入CSV数据
2020/07/28 Python
税务会计岗位职责
2014/02/18 职场文书
社区文化建设方案
2014/05/02 职场文书
企业法人代表任命书
2014/06/06 职场文书
应届生简历自我评价
2015/03/11 职场文书
2015年医院护理部工作总结
2015/04/23 职场文书
vue+elementui 实现新增和修改共用一个弹框的完整代码
2021/06/08 Vue.js
Vue中Object.assign清空数据报错的解决方案
2022/03/03 Vue.js
我国拿下天问一号火星着陆区附近 22 个地理实体命名:平乐、西柏坡、古田、漠河等
2022/04/29 数码科技