python模块介绍- SocketServer 网络服务框架
2013-05-22磁针石
#承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq 37391319 博客:http://blog.csdn.net/oychw
#版权所有,转载刊登请来函联系
# 深圳测试自动化python项目接单群113938272深圳会计软件测试兼职 6089740
#深圳地摊群 66250781武冈洞口城步新宁乡情群49494279
#自动化测试和python群组: http://groups.google.com/group/automation_testing_python
#参考资料:《The Python Standard Library by Example2011》
# http://docs.python.org/2/howto/sockets.html
11.3 SocketServer– 网络服务框架
SocketServer简化了网络服务器的编写。它有4个类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer。这4个类是同步进行处理的,另外通过ForkingMixIn和ThreadingMixIn类来支持异步。
创建服务器的步骤。首先,你必须创建一个请求处理类,它是BaseRequestHandler的子类并重载其handle()方法。其次,你必须实例化一个服务器类,传入服务器的地址和请求处理程序类。最后,调用handle_request()或serve_forever()。
当继承自ThreadingMixIn为螺纹连接行为,你应该明确线程异常关闭时如何处理。ThreadingMixIn类的daemon_threads指示服务器是否应该等待线程终止,默认值为False。
无论用什么网络协议,服务器类有相同的外部方法和属性。
11.3.1 服务器类型
注意:BaseServer不直接对外服务。
+------------+
+------------+
|
v
+-----------+ +------------------+
|TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+
|
v
+-----------+ +--------------------+
|UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+
11.3.2 服务器对象(略)
11.3.3 实现服务器
通常情况下使用默认配置即可,一下方法可重载。
•verify_request(request, client_address): 返回True如果处理请求,反之返回False。忽略它。比如只处理指定ip区间的请求。
•process_request(request, client_address):调用finish_request()处理请求,也可以创建单独的现成或者进程。
•finish_request(request,client_address):创建一个请求处理实例,调用实例的handle()。
11.3.4 请求处理器
处理器接收数据并决定如何操作。它负责在socket层之上实现协议(i.e.,HTTP, XML-RPC, or AMQP).可以重载的方法如下:
• setup(): 准备请求处理. StreamRequestHandler中会创建文件类似的对象。forreading from and writing to the socket.
• handle(): 处理请求。解析传入的请求,处理数据,并发送响应。
• finish(): 环境清理。
通常只需要重载handle。
11.3.5 Echo实例
完整起见,这里列出了所有方法。后面有简化版本。另外,服务器和客服端放在一个脚本。
importlogging
import sys
importSocketServer
logging.basicConfig(level=logging.DEBUG,
format='%(name)s:%(message)s',
)
classEchoRequestHandler(SocketServer.BaseRequestHandler):
def __init__(self, request, client_address,server):
self.logger =logging.getLogger('EchoRequestHandler')
self.logger.debug('__init__')
SocketServer.BaseRequestHandler.__init__(self, request,
client_address,
server)
return
def setup(self):
self.logger.debug('setup')
returnSocketServer.BaseRequestHandler.setup(self)
def handle(self):
self.logger.debug('handle')
# Echo the back to the client
data = self.request.recv(1024)
self.logger.debug('recv()->"%s"', data)
self.request.send(data)
return
def finish(self):
self.logger.debug('finish')
returnSocketServer.BaseRequestHandler.finish(self)
classEchoServer(SocketServer.TCPServer):
def __init__(self, server_address,
handler_class=EchoRequestHandler,
):
self.logger = logging.getLogger('EchoServer')
self.logger.debug('__init__')
SocketServer.TCPServer.__init__(self,server_address,
handler_class)
return
def server_activate(self):
self.logger.debug('server_activate')
SocketServer.TCPServer.server_activate(self)
return
def serve_forever(self, poll_interval=0.5):
self.logger.debug('waiting forrequest')
self.logger.info('Handling requests,press <Ctrl-C> to quit')
SocketServer.TCPServer.serve_forever(self,poll_interval)
return
def handle_request(self):
self.logger.debug('handle_request')
returnSocketServer.TCPServer.handle_request(self)
def verify_request(self, request,client_address):
self.logger.debug('verify_request(%s,%s)',
request,client_address)
returnSocketServer.TCPServer.verify_request(self, request,
client_address)
def process_request(self, request,client_address):
self.logger.debug('process_request(%s,%s)',
request,client_address)
returnSocketServer.TCPServer.process_request(self, request,
client_address)
def server_close(self):
self.logger.debug('server_close')
returnSocketServer.TCPServer.server_close(self)
def finish_request(self, request, client_address):
self.logger.debug('finish_request(%s,%s)',
request,client_address)
returnSocketServer.TCPServer.finish_request(self, request,
client_address)
def close_request(self, request_address):
self.logger.debug('close_request(%s)',request_address)
returnSocketServer.TCPServer.close_request(self,
request_address)
def shutdown(self):
self.logger.debug('shutdown()')
returnSocketServer.TCPServer.shutdown(self)
if __name__== '__main__':
import socket
import threading
address = ('localhost', 0) # let the kernelassign a port
server = EchoServer(address,EchoRequestHandler)
ip, port = server.server_address # whatport was assigned?
# Start the server in a thread
t =threading.Thread(target=server.serve_forever)
t.setDaemon(True) # don't hang on exit
t.start()
logger = logging.getLogger('client')
logger.info('Server on %s:%s', ip, port)
# Connect to the server
logger.debug('creating socket')
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
logger.debug('connecting to server')
s.connect((ip, port))
# Send the data
message = 'Hello, world'
logger.debug('sending data:"%s"', message)
len_sent = s.send(message)
# Receive a response
logger.debug('waiting for response')
response = s.recv(len_sent)
logger.debug('response from server:"%s"', response)
# Clean up
server.shutdown()
logger.debug('closing socket')
s.close()
logger.debug('done')
server.socket.close()
执行结果:
]#./SocketServer_echo.py
EchoServer:__init__
EchoServer:server_activate
EchoServer:waiting for request
EchoServer:Handling requests, press <Ctrl-C> to quit
client:Server on 127.0.0.1:48354
client:creating socket
client:connecting to server
client:sending data: "Hello, world"
EchoServer:verify_request(<socket._socketobject object at 0x9f698b4>, ('127.0.0.1',38337))
EchoServer:process_request(<socket._socketobject object at 0x9f698b4>, ('127.0.0.1',38337))
client:waiting for response
EchoServer:finish_request(<socket._socketobject object at 0x9f698b4>, ('127.0.0.1',38337))
EchoRequestHandler:__init__
EchoRequestHandler:setup
EchoRequestHandler:handle
EchoRequestHandler:recv()->"Hello, world"
EchoRequestHandler:finish
client:response from server: "Hello, world"
EchoServer:shutdown()
EchoServer:close_request(<socket._socketobject object at 0x9f698b4>)
client:closing socket
client: done
简化版本:
importSocketServer
classEchoRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
# Echo the back to the client
data = self.request.recv(1024)
self.request.send(data)
return
if __name__== '__main__':
import socket
import threading
address = ('localhost', 0) # let the kernelassign a port
server = SocketServer.TCPServer(address,EchoRequestHandler)
ip, port = server.server_address # whatport was assigned?
t =threading.Thread(target=server.serve_forever)
t.setDaemon(True) # don't hang on exit
t.start()
# Connect to the server
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((ip, port))
# Send the data
message = 'Hello, world'
print 'Sending : "%s"' % message
len_sent = s.send(message)
# Receive a response
response = s.recv(len_sent)
print 'Received: "%s"' % response
# Clean up
server.shutdown()
s.close()
server.socket.close()
执行结果:
#./SocketServer_echo_simple.py
Sending :"Hello, world"
Received:"Hello, world"
11.3.6 Threading 和 Forking
线程:
importthreading
importSocketServer
classThreadedEchoRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
# Echo the back to the client
data = self.request.recv(1024)
cur_thread = threading.currentThread()
response = '%s: %s' % (cur_thread.getName(),data)
self.request.send(response)
return
classThreadedEchoServer(SocketServer.ThreadingMixIn,
SocketServer.TCPServer,
):
pass
if __name__== '__main__':
import socket
import threading
address = ('localhost', 0) # let the kernelassign a port
server = ThreadedEchoServer(address,ThreadedEchoRequestHandler)
ip, port = server.server_address # whatport was assigned?
t = threading.Thread(target=server.serve_forever)
t.setDaemon(True) # don't hang on exit
t.start()
print 'Server loop running in thread:',t.getName()
# Connect to the server
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((ip, port))
# Send the data
message = 'Hello, world'
print 'Sending : "%s"' % message
len_sent = s.send(message)
# Receive a response
response = s.recv(1024)
print 'Received: "%s"' % response
# Clean up
server.shutdown()
s.close()
server.socket.close()
执行结果:
# ./SocketServer_threaded.py
Server looprunning in thread: Thread-1
Sending :"Hello, world"
Received:"Thread-2: Hello, world"
进程:
import os
importSocketServer
classForkingEchoRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
# Echo the back to the client
data = self.request.recv(1024)
cur_pid = os.getpid()
response = '%s: %s' % (cur_pid, data)
self.request.send(response)
return
classForkingEchoServer(SocketServer.ForkingMixIn,
SocketServer.TCPServer,
):
pass
if __name__== '__main__':
import socket
import threading
address = ('localhost', 0) # let the kernelassign a port
server = ForkingEchoServer(address,ForkingEchoRequestHandler)
ip, port = server.server_address # whatport was assigned?
t =threading.Thread(target=server.serve_forever)
t.setDaemon(True) # don't hang on exit
t.start()
print 'Server loop running in process:',os.getpid()
# Connect to the server
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((ip, port))
# Send the data
message = 'Hello, world'
print 'Sending : "%s"' % message
len_sent = s.send(message)
# Receive a response
response = s.recv(1024)
print 'Received: "%s"' % response
# Clean up
server.shutdown()
s.close()
server.socket.close()
执行结果:
# ./SocketServer_forking.py
Server loop running in process: 6288
Sending : "Hello, world"
Received: "6290: Hello, world"
SocketServer(http://docs.python.org/lib/module-SocketServer.html) Standard library documentationfor this module
asyncore (page 619) Use asyncore tocreate asynchronous servers that do not block
while processing a request.
SimpleXMLRPCServer (page 714) XML-RPCserver built using SocketServer.