python服务端编程_pythonweb服务器编程(四)

#coding=utf-8

importsocketimportsysfrom multiprocessing importProcessimportreclassWSGIServer(object):

addressFamily=socket.AF_INET

socketType=socket.SOCK_STREAM

requestQueueSize= 5

def __init__(self, serverAddress):#创建一个tcp套接字

self.listenSocket =socket.socket(self.addressFamily,self.socketType)#允许重复使用上次的套接字绑定的port

self.listenSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)#绑定

self.listenSocket.bind(serverAddress)#变为被动,并制定队列的长度

self.listenSocket.listen(self.requestQueueSize)

self.servrName= "localhost"self.serverPort= serverAddress[1]defserveForever(self):'循环运行web服务器,等待客户端的链接并为客户端服务'

whileTrue:#等待新客户端到来

self.clientSocket, client_address =self.listenSocket.accept()#方法2,多进程服务器,并发服务器于多个客户端

newClientProcess = Process(target =self.handleRequest)

newClientProcess.start()#因为创建的新进程中,会对这个套接字+1,所以需要在主进程中减去依次,即调用一次close

self.clientSocket.close()defsetApp(self, application):'设置此WSGI服务器调用的应用程序入口函数'self.application=applicationdefhandleRequest(self):'用一个新的进程,为一个客户端进行服务'self.recvData= self.clientSocket.recv(2014)

requestHeaderLines=self.recvData.splitlines()for line inrequestHeaderLines:print(line)

httpRequestMethodLine=requestHeaderLines[0]

getFileName= re.match("[^/]+(/[^ ]*)", httpRequestMethodLine).group(1)print("file name is ===>%s"%getFileName) #for test

if getFileName[-3:] != ".py":if getFileName == '/':

getFileName= documentRoot + "/index.html"

else:

getFileName= documentRoot +getFileNameprint("file name is ===2>%s"%getFileName) #for test

try:

f=open(getFileName)exceptIOError:

responseHeaderLines= "HTTP/1.1 404 not found\r\n"responseHeaderLines+= "\r\n"responseBody= "====sorry ,file not found===="

else:

responseHeaderLines= "HTTP/1.1 200 OK\r\n"responseHeaderLines+= "\r\n"responseBody=f.read()

f.close()finally:

response= responseHeaderLines +responseBody

self.clientSocket.send(response)

self.clientSocket.close()else:#处理接收到的请求头

self.parseRequest()#根据接收到的请求头构造环境变量字典

env =self.getEnviron()#调用应用的相应方法,完成动态数据的获取

bodyContent =self.application(env, self.startResponse)#组织数据发送给客户端

self.finishResponse(bodyContent)defparseRequest(self):'提取出客户端发送的request'requestLine=self.recvData.splitlines()[0]

requestLine= requestLine.rstrip('\r\n')

self.requestMethod, self.path, self.requestVersion= requestLine.split(" ")defgetEnviron(self):

env={}

env['wsgi.version'] = (1, 0)

env['wsgi.input'] =self.recvData

env['REQUEST_METHOD'] = self.requestMethod #GET

env['PATH_INFO'] = self.path #/index.html

returnenvdef startResponse(self, status, response_headers, exc_info=None):

serverHeaders=[

('Date', 'Tue, 31 Mar 2016 10:11:12 GMT'),

('Server', 'WSGIServer 0.2'),

]

self.headers_set= [status, response_headers +serverHeaders]deffinishResponse(self, bodyContent):try:

status, response_headers=self.headers_set#response的第一行

response = 'HTTP/1.1 {status}\r\n'.format(status=status)#response的其他头信息

for header inresponse_headers:

response+= '{0}: {1}\r\n'.format(*header)#添加一个换行,用来和body进行分开

response += '\r\n'

#添加发送的数据

for data inbodyContent:

response+=data

self.clientSocket.send(response)finally:

self.clientSocket.close()#设定服务器的端口

serverAddr = (HOST, PORT) = '', 8888

#设置服务器静态资源的路径

documentRoot = './html'

#设置服务器动态资源的路径

pythonRoot = './wsgiPy'

defmakeServer(serverAddr, application):

server=WSGIServer(serverAddr)

server.setApp(application)returnserverdefmain():if len(sys.argv) < 2:

sys.exit('请按照要求,指定模块名称:应用名称,例如 module:callable')#获取module:callable

appPath = sys.argv[1]#根据冒号切割为module和callable

module, application = appPath.split(':')#添加路径套sys.path

sys.path.insert(0, pythonRoot)#动态导入module变量中指定的模块

module = __import__(module)#获取module变量中制定的模块的application变量指定的属性

application =getattr(module, application)

httpd=makeServer(serverAddr, application)print('WSGIServer: Serving HTTP on port {port} ...\n'.format(port=PORT))

httpd.serveForever()if __name__ == '__main__':

main()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值