视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Python实现简单的HttpServer服务器
2020-11-27 14:22:49 责编:小OO
文档

本篇文章主要介绍了Python实现简单的HttpServer服务器示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

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

    下载本文
    显示全文
    专题