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

作者:小胜的IT空间 时间:2021-02-07 21:29:35 

要写一个类似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

来源:http://www.cnblogs.com/jiashengmei/p/6346946.html

标签:Python,HttpServer
0
投稿

猜你喜欢

  • 手写一个python迭代器过程详解

    2021-06-29 07:45:23
  • 彻底理解Python中的yield关键字

    2021-02-23 16:31:42
  • TensorFlow2.0矩阵与向量的加减乘实例

    2023-12-30 13:21:00
  • python对json的相关操作实例详解

    2022-03-27 20:15:06
  • 解析MYSQL显示表信息的方法

    2024-01-15 12:17:49
  • Python3.4 splinter(模拟填写表单)使用方法

    2023-02-15 13:57:23
  • python中requests小技巧

    2023-12-11 19:31:21
  • 最令人蛋疼的10种用户体验设计师

    2011-08-05 18:51:07
  • windows环境中利用celery实现简单任务队列过程解析

    2023-08-09 12:15:28
  • MySQL中Nested-Loop Join算法小结

    2024-01-18 14:26:36
  • Golang 中反射的应用实例详解

    2024-02-12 03:12:06
  • Django 解决上传文件时,request.FILES为空的问题

    2021-10-21 19:37:41
  • Python数据分析之双色球统计单个红和蓝球哪个比例高的方法

    2022-08-13 07:55:01
  • 深入浅出MySQL双向复制技术

    2009-03-25 15:40:00
  • 在ASP.NET 2.0中操作数据之四十四:DataList和Repeater数据排序(三)

    2023-07-02 04:45:57
  • numpy中三维数组中加入元素后的位置详解

    2021-02-28 10:25:14
  • Java正则表达式判断字符串中是否包含中文示例

    2022-02-18 00:10:56
  • python第三方库visdom的使用入门教程

    2021-12-08 22:32:51
  • C# Ado.net实现读取SQLServer数据库存储过程列表及参数信息示例

    2024-01-12 20:16:06
  • 全局安装 Vue cli3 和 继续使用 Vue-cli2.x操作

    2024-05-28 15:59:34
  • asp之家 网络编程 m.aspxhome.com