主要学习服务器的异步使用
SocketServer简化了网络服务器的编写。它有4个类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer。这4个类是同步进行处理的,另外通过ForkingMixIn和ThreadingMixIn类来支持异步。
创建服务器的步骤
- 创建一个请求处理类,它是BaseRequestHandler的子类并重载其handle()方法。
- 实例化一个服务器类,传入服务器的地址和请求处理程序类。
- 调用handle_request()(一般是调用其他事件循环或者使用select())或serve_forever()。
集成ThreadingMixIn类时需要处理异常关闭。daemon_threads指示服务器是否要等待线程终止,要是线程互相独立,必须要设置为True,默认是False。
使用基于多进程,ForkingMinIn 支持异步
import os
import socket
import threading
import SocketServer
# 构造客户端
class ForkingClient():
def __init__(self, ip, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.connect((ip, port))
def run(self):
crtpid = os.getpid()
print "PID: %s " % crtpid
send_length = self.sock.send("hello, world!")
print "sent %d characters..." % send_length
res = self.sock.recv(2048)
print "PID %s received: %s" % (crtpid, res)
def shutdown(self):
self.sock.close()
# 写服务端处理函数
class ForkingServerRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request.recv(2048)
crtpid = os.getpid()
res = "%s: %s" % (crtpid, data)
print res
self.request.send(res)
return
# 继承
class ForkingServer(SocketServer.ForkingMixIn, SocketServer.TCPServer):
pass
def main():
server = ForkingServer(('localhost', 8989), ForkingServerRequestHandler)
ip, port = server.server_address
server_thread = threading.Thread(target=server.serve_forever)
server_thread.setDaemon(True)
server_thread.start()
print 'Server loop running PID: %s' % os.getpid()
client_1 = ForkingClient(ip, port)
client_2 = ForkingClient(ip, port)
client_1.run()
client_2.run()
client_1.shutdown()
client_2.shutdown()
server.socket.close()
if __name__ == '__main__':
main()
执行可以看到
duck@duck:~/sockdir/chapter_2$ python forkser.py
Server loop running PID: 22649
PID: %s 22649
sent 13 characters...
22651: hello, world!
PID 22649 received: 22651: hello, world!
PID: %s 22649
sent 13 characters...
22652: hello, world!
PID 22649 received: 22652: hello, world!
现在用ThreadingMixIn
优势:线程之间共享应用状态容易,避免进程间通信