异步混合:
为了建立异步处理机制,需要使用ThreadingMixIn和ForkingMixIn类。
以下是一个使用ThreadingMixIn类的示例:
<strong>import socket
import threading
import socketserver
class ThreadedTCPRequestHandler(socketserver</strong><span style="color:#cc0000;">.BaseRequestHandler):
</span>
<span style="color:#ff0000;"> def handle(self):
</span><strong> data = str(self.request.recv(1024), 'ascii')
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(</strong><span style="color:#ff0000;">cur_thread.name, data</span><strong>), 'ascii')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn,</strong> <span style="color:#ff0000;"><strong>socketserver.TCPServer):</strong>
</span><strong> pass
def client(ip, port, message):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, port))
try:
sock.sendall(bytes(message, 'ascii'))
response = str(sock.recv(1024), 'ascii')
print("Received: {}".format(response))
finally:
sock.close()
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
HOST, PORT = "localhost", 0</strong>
<span style="color:#ff0000;">server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
</span><span style="color:#ff0000;"> ip, port = server.server_address
</span><strong>
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(</strong><span style="color:#ff0000;">target=server.serve_forever</span><strong>)
# Exit the server thread when the main thread terminates</strong>
<span style="color:#ff0000;">server_thread.daemon = True
server_thread.start()
</span><strong> print("Server loop running in thread:", server_thread.name)</strong>
<span style="color:#ff0000;">client(ip, port, "Hello World 1")
client(ip, port, "Hello World 2")
client(ip, port, "Hello World 3")
</span>
server.shutdown()
结果应该类似这样:
Server loop running in thread: Thread-1 Received: Thread-2: Hello World 1 Received: Thread-3: Hello World 2 Received: Thread-4: Hello World 3
SocketServer是标准库中一个很具有代表性的库。它基于socket提供一套快速建立socket服务器的框架,并可以通过Mix-in的技巧让单线程服务器进化为多线程或多进程服务器。Socketserver.py里面的类很多,下面一个一个介绍并介绍它们之间关系。
BaseServer、TCPServer、UDPServer,前者是后两者的父类。在父类中实现了TCP与UDP服务器可以共用的方法,并留下了需要在子类中实现的抽象类。因此在实际工作中,我们一般不应该继承BaseServer类,除非你是为了自己去实现或重载某些方法。另外,还有UnixStreamServer和UnixDatagramServer分别继承自TCPserver和UDPServer。这两个带Unix字样的类是用来构建*nix下本地socket的服务器(本地socket访问速度更快,但只能用在本机的进程间通信)
接下来是ForkingMixIn和ThreadingMixIn两个混合类,它们都提供Server类中process_request方法的新实现,前者在处理每次用户连接的时候都会开启新的进程,而后者会开启新的线程。想要让Server类实现并发处理,只用利用多重继承即可。或者直接使用已经混合好的
class ForkingUDPServer(ForkingMixIn, UDPServer): pass
class ForkingTCPServer(ForkingMixIn, TCPServer): pass
class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
最后没有介绍的是BaseRequestHandler、StreamRequestHandler、DatagramRequestHandler,同Server一样,前者是后两者的父类用来提供公用的方法
通常在使用SocketServer的时候我们只用自己实例化一个合适的Server类,并在实例化时传递其监听的IP、端口,以及之前继承自某个RequestHandler的类(需要自行实现hanle方法,作为server的请求处理器)
这里需要特别注意的:
1.IP和端口是作为一个元组传递的而不是两个单独的参数。
2.每个客户连接都会在hanle方法运行完之后被关闭,你如果不想关闭就需要重写Server中的def shutdown_request(self, request)方法
1.前言:
虽说用Python编写简单的网络程序很方便,但复杂一点的网络程序还是用现成的框架比较好。这样就可以专心事务逻辑,而不是套接字的各种细节。SocketServer模块简化了编写网络服务程序的任务。同时SocketServer模块也是Python标准库中很多服务器框架的基础。
2.网络服务类:
SocketServer提供了4个基本的服务类:
TCPServer针对TCP套接字流
UDPServer针对UDP数据报套接字
UnixStreamServer和UnixDatagramServer针对UNIX域套接字,不常用。
它们的继承关系如下:
+------------+
| BaseServer |
+------------+
|
v
+-----------+ +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+
|
v
+-----------+ +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+
2.1异步处理:
这个四个服务类都是同步处理请求的。一个请求没处理完不能处理下一个请求。要想支持异步模型,可以利用多继承让server类继承ForkingMixIn 或 ThreadingMixIn mix-in classes。
ForkingMixIn利用多进程(分叉)实现异步。
ThreadingMixIn利用多线程实现异步。
3.请求处理类:
要实现一项服务,还必须派生一个handler class请求处理类,并重写父类的handle()方法。handle方法就是用来专门是处理请求的。该模块是通过服务类和请求处理类组合来处理请求的。
SocketServer模块提供的请求处理类有BaseRequestHandler,以及它的派生类StreamRequestHandler和DatagramRequestHandler。从名字看出可以一个处理流式套接字,一个处理数据报套接字。
4.总结用SocketServer创建一个服务的步骤:
1.创建一个request handler class(请求处理类),继承自BaseRequestHandler class并重写它的handle()方法,该方法将处理到的请求。
2.实例化一个server class对象,并将服务的地址和之前创建的request handler class传递给它。
3.调用server class对象的handle_request() 或 serve_forever()方法来开始处理请求。
一个基于SocketServer的服务器示例:
- from SocketServer import TCPServer,StreamRequestHandler
- #定义请求处理类
- class Handler(StreamRequestHandler):
- def handle(self):
- addr = self.request.getpeername()
- print ‘Got connection from ‘,addr
- self.wfile.write(‘Thank you for connecting’)
- server = TCPServer((”,1234), handler) #实例化服务类对象
- server.server_forever() #开启服务
<span style="font-size:18px;">from SocketServer import TCPServer,StreamRequestHandler
#定义请求处理类
class Handler(StreamRequestHandler):
def handle(self):
addr = self.request.getpeername()
print 'Got connection from ',addr
self.wfile.write('Thank you for connecting')
server = TCPServer(('',1234), handler) #实例化服务类对象
server.server_forever() #开启服务
</span>
5.实现异步,支持多连接
前面介绍服务类时提到过,四个基本的服务类默认是同步模型的。要想支持异步可以利用多继承从ForkingMixIn 或ThreadingMixInmix-in classes和一个基本的服务类继承来定义一个支持异步的服务类。比如:
class Server(ThreadingMixIn, TCPServer): pass
ForkingMixIn 要考虑进程间的通信。ThreadingMixIn要考虑线程访问同一变量时的同步和互斥。
一个使用了多线程处理的服务器示例:
- from SocketServer import TCPServer, ThreadingMixIn, StreamRequestHandler
- #定义支持多线程的服务类,注意是多继承
- class Server(ThreadingMixIn, TCPServer): pass
- #定义请求处理类
- class Handler(StreamRequestHandler):
- def handle(self):
- addr = self.request.getpeername()
- print ‘Got connection from ‘,addr
- self.wfile.write(‘Thank you for connection’)
- server = Server((”, 1234), Handler) #实例化服务类
- server.serve_forever() #开启服务
<span style="font-size:18px;">from SocketServer import TCPServer, ThreadingMixIn, StreamRequestHandler
#定义支持多线程的服务类,注意是多继承
class Server(ThreadingMixIn, TCPServer): pass
#定义请求处理类
class Handler(StreamRequestHandler):
def handle(self):
addr = self.request.getpeername()
print 'Got connection from ',addr
self.wfile.write('Thank you for connection')
server = Server(('', 1234), Handler) #实例化服务类
server.serve_forever() #开启服务</span>