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 列表list使用介绍
Nov 30 Python
Python网页解析利器BeautifulSoup安装使用介绍
Mar 17 Python
python将字典内容存入mysql实例代码
Jan 18 Python
浅析python协程相关概念
Jan 20 Python
Python 实现异步调用函数的示例讲解
Oct 14 Python
对django中render()与render_to_response()的区别详解
Oct 16 Python
python将txt文件读入为np.array的方法
Oct 30 Python
python中for循环输出列表索引与对应的值方法
Nov 07 Python
python write无法写入文件的解决方法
Jan 23 Python
python实现LBP方法提取图像纹理特征实现分类的步骤
Jul 11 Python
如何安装并在pycharm使用selenium的方法
Apr 30 Python
python之pygame模块实现飞机大战完整代码
Nov 29 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
js+php实现静态页面实时调用用户登陆状态的方法
2015/01/04 PHP
帝国cms目录结构分享
2015/07/06 PHP
Yii2框架BootStrap样式的深入理解
2016/11/07 PHP
php判断str字符串是否是xml格式数据的方法示例
2017/07/26 PHP
实例介绍PHP中zip_open()函数用法
2019/02/15 PHP
InnerHtml和InnerText的区别分析
2009/03/13 Javascript
谈谈关于JavaScript 中的 MVC 模式
2013/04/11 Javascript
关于jQuery $.isNumeric vs. $.isNaN vs. isNaN
2013/04/15 Javascript
js判断60秒以及倒计时示例代码
2014/01/24 Javascript
在linux中使用包管理器安装node.js
2015/03/13 Javascript
JavaScript取得WEB安全颜色列表的方法
2015/07/14 Javascript
JavaScript学习笔记整理之引用类型
2016/01/22 Javascript
浅谈js中字符和数组一些基本算法题
2016/08/15 Javascript
使用jquery的jsonp如何发起跨域请求及其原理详解
2017/08/17 jQuery
浅谈webpack下的AOP式无侵入注入
2017/11/12 Javascript
Angular 如何使用第三方库的方法
2018/04/18 Javascript
Angular动态绑定样式及改变UI框架样式的方法小结
2018/09/03 Javascript
vue子组件改变父组件传递的prop值通过sync实现数据双向绑定(DEMO)
2020/02/01 Javascript
vue 子组件修改data或调用操作
2020/08/07 Javascript
Python实现基于权重的随机数2种方法
2015/04/28 Python
在Python的列表中利用remove()方法删除元素的教程
2015/05/21 Python
用python写个自动SSH登录远程服务器的小工具(实例)
2017/06/17 Python
python cs架构实现简单文件传输
2020/03/20 Python
python3 爬取图片的实例代码
2018/11/06 Python
利用Python半自动化生成Nessus报告的方法
2019/03/19 Python
python3.6编写的单元测试示例
2019/08/17 Python
Python如何使用函数做字典的值
2019/11/30 Python
Mankind西班牙男士护肤品网站:购买皮肤护理、护发和剃须
2017/04/27 全球购物
英国皇家邮政海外旗舰店:Royal Mail
2018/02/21 全球购物
运动会广播稿20字
2014/02/18 职场文书
我是一名护士演讲稿
2014/08/28 职场文书
群众路线问题查摆对照检查材料
2014/10/04 职场文书
全陪导游词
2015/02/04 职场文书
仰望星空观后感
2015/06/10 职场文书
如何使用Maxwell实时同步mysql数据
2021/04/08 MySQL
漫画《催眠麦克风-Dawn Of Divisions》第二卷PV公开
2022/04/05 日漫