学习python是因为当时学习的C语言实现一个东西太难了,做一个图形界面又丑又难看,而且还很难写。python高度封装,简洁,第三方库也超多,像列表这种东西用起来真是太爽了,对于字符串简直无所不能,所以还是那句话人生苦短,我用python。当时对语言的性能并没有太多的认知,写代码大多也就一两百行的样子,内存、CPU都是可以随意挥霍的东西。python的性能还是比不上C语言,但是开发速度还是很可以的,大家都说一种很折中的go语言,开发速度与执行效率介于python和C语言之间,以后有时间在学校吧。
通过看源码webbech和tinyhttpd熟悉语言怎么处理http请求,那么用python语言就是太容易实现了。下面我用python实现一个多线程的伪源站服务器,利用python提供的SocketServer,每来一个连接,我就返回2500000字节的文件。源码如下:
#! /usr/bin/python2.7
#coding:utf-8
import SocketServer
import datetime
#import os
import sys # sys.argc sys.argv
import time # for sleep
gHttpbody=""
def CreateHttpBodyData():
sLineBody = "test-data-body "
for i in range(4):
sLineBody += sLineBody
sLineBody += "\n"
sRspBody = ""
for i in range(10000):
sLine = "__%05d__" % (i)
sRspBody += sLine + sLineBody
return sRspBody
class Myserver(SocketServer.BaseRequestHandler):
def RcvInit(self):
self.sHeadInfo = ""
self.sReqLine = ""
self.sClientIP = ""
self.sClientPort = 0
def RcvHeadInfo(self):
sTempData = ""
while True:
receiveData = self.request.recv(4096)
if receiveData is None:
print "no receive data"
return False
if len(receiveData) == 0:
print "RcvHeadInfo : receive empty data"
return False
sTempData = sTempData + receiveData
iPos = sTempData.find("\r\n\r\n")
if iPos >= 0:
break
if len(sTempData) > 1024:
print "error, receive data too long:",len(sTempData)
return False
self.sHeadInfo = sTempData[0:iPos]
print self.sHeadInfo
return True
def GetReqLine(self):
aHeadList = self.sHeadInfo.split("\r\n")
sMethod = "GET "
for sHeadLine in aHeadList:
iPos = sHeadLine.find(sMethod)
if iPos >= 0:
iPos = iPos + len(sMethod)
self.sReqLine = sHeadLine[iPos:]
self.sReqLine = self.sReqLine.strip()
break
return self.sReqLine
def GetHeader(self, head_name):
head_begin = self.sHeadInfo.find(head_name)
if head_begin < 0:
return ""
head_begin += len(head_name)
head_end = self.sHeadInfo.find("\r\n", head_begin)
if head_end < 0:
print "can not find head_end"
return ""
head_val = self.sHeadInfo[head_begin:head_end]
return head_val
def DoRsp304(self, sReqLine):
aHeaders = []
aHeaders.append(("Server", "python-test"))
if(sReqLine.find("close=0") < 0):
aHeaders.append(("Connection", "close"))
aHeaders.append(("TestHttp", "python Server"))
aHeaders.append(("author", "vaynedu-ying"))
aHeaders.append(("Last-Modified", "Fri, 28 Oct 6666 66:66:66 GMT"))
aHeaders.append(("Content-Length", "0"))
sSendHeader = "HTTP/1.1 304 xxx\r\n"
for (sHeadName, sHeadValue) in aHeaders:
sSendHeader += sHeadName + ": " + sHeadValue + "\r\n"
self.request.sendall(sSendHeader)
self.request.sendall("\r\n") #结束信息
print sSendHeader
return
def GetChipList(self, sReqLine, iChipNum=10):
global gHttpbody
sRspBody = gHttpbody
iBodylen = len(sRspBody)
iChipLen = iBodylen/iChipNum
asChipList = []
for i in range(iChipNum-1):
sChip = sRspBody[iChipLen*i : iChipLen*(i+1)]
asChipList.append(sChip)
sChip = sRspBody[iChipLen*(iChipNum-1): ]
asChipList.append(sChip)
return (asChipList, iBodylen)
def DoRspBody(self, sReqLine):
global gHttpbody
aHeaders = []
aHeaders.append(("Server","python-test"))
if(sReqLine.find("close=0") < 0):
aHeaders.append(("Connection", "close"))
aHeaders.append(("TestHttp", "python Server"))
aHeaders.append(("author", "vaynedu-ying"))
aHeaders.append(("Content-type", "video/mp2t"))
#aHeaders.append(("Last-Modified", "Fri, 2 Oct 2017 00:00:00 GMT"))
aHeaders.append(("Last-Modified", "Fri, 28 Oct 2016 12:35:18 GMT"))
(asChipList, iBodylen) = self.GetChipList(sReqLine, 10)
sLenValue = str(iBodylen)
#print sLenValue
aHeaders.append(("Content-Length", sLenValue))
sSendHeader = "HTTP/1.1 200 OK\r\n"
for(sHeadName, sHeadValue) in aHeaders:
sSendHeader += sHeadName + ": " + sHeadValue + "\r\n"
self.request.sendall(sSendHeader)
self.request.sendall("\r\n")
print sSendHeader
iNum = 0
for sChip in asChipList:
self.request.sendall(sChip)
time.sleep(0.01)
return
def do_GET(self, sReqLine):
NowTime = datetime.datetime.now()
sTime = NowTime.strftime("%Y-%m-%d_%H-%M-%S")
print sTime, " GET ", sReqLine
sModified = self.GetHeader("If-Modified-Since: ")
if (sModified != ""):
self.DoRsp304(sReqLine)
return
sNodeMatch = self.GetHeader("If-None-Match: ")
if (sNodeMatch != ""):
self.DoRsp304(sReqLine)
return
self.DoRspBody(sReqLine)
return
def setup(self):
(sIP, iPort) = self.request.getpeername()
self.RcvInit()
self.sClientIP = sIP
self.sClientPort = iPort
# print "client ip : ", sIP, "client port: ", iPort
def handle(self):
bIsHeadRcv = self.RcvHeadInfo()
if bIsHeadRcv == False:
self.request.close()
return
sReqLine = self.GetReqLine()
if sReqLine == "":
self.request.close()
return
self.do_GET(sReqLine)
time.sleep(5)
self.request.close()
return
def finish(self):
print "client ip : ", self.sClientIP, "client port: ", self.sClientPort, " is close"
if __name__ == '__main__':
if len(sys.argv) >= 3:
sLocalIP = sys.argv[1]
sLocalPort = sys.argv[2]
else:
sLocalIP = r"localhost"
sLocalPort = "8080"
gHttpbody = CreateHttpBodyData()
print "test http body length: ", len(gHttpbody)
server = SocketServer.ThreadingTCPServer((sLocalIP, int(sLocalPort)), Myserver)
print "Starting server, use <Ctrl + C> to stop"
server.serve_forever()
服务端效果
客户端效果
最后在说一下,原来从服务器上下载的文件都是按照上一次修改时间来计算的,看来我之前理解错误了。
如果有什么问题,欢迎大家讨论指正!!!