为了快速搭建服务器,标准库中有个高级模块SocketServer
它提供了一些可供使用的类(使用类就是会了封装那些繁琐的细节)
我们来看看SocketServer中提供的2个重要的类
- TCPServer/UDPServer 网络同步服务器
- StreamRequestHandler/DatagramRequestHandler 2种处理器,处理客户请求
注:SocketServer请求处理器的默认行为是:接收连接,得到请求,之后断开连接。也就是说如果一个客户想说好几句话时,必须得说一句,建立一个Socket
本章还提到了“事件驱动”
事件驱动:只有在事件出现的时候,程序才做出反应
什么是事件? 你点击一个按钮,就是触发一个事件,电脑会对此做出反应。发生什么事件就调用相应的函数进行处理,这就是事件驱动。我们可以定义事件类,并在这些类中定义处理器。这样就可以快速的知道是什么事件,进而快速调用相应处理器解决。这也是面向对象的编程思想。
非事件驱动:个人理解是发生一个事件后,程序首先会执行一系列操作来确定这是什么事件,确定下来后才会采用对应的方法进行解决。
下面的实例会实现一个请求处理器,只有当客户提出请求时,就会调用该处理器来处理请求。没有客户接入时,CPU会暂时休息,这样就对CPU进行有效利用。
创建TCP同步服务器
#-*- coding:utf-8 -*-
#导入一个TCP服务器类和一个流处理器(处理TCP请求)
from SocketServer import (TCPServer as TCP, \
StreamRequestHandler as SRH)
from time import ctime
HOST = 'localhost'
PORT = 20000
ADDR = (HOST, PORT)
class RequestHandler(SRH):
def handle(self):
print "...connected from", self.client_address
#处理器类可以像处理文件一样处理Socket数据
self.wfile.write("[%s]%s"% (ctime(),self.rfile.readline()))
tcpServer = TCP(ADDR, RequestHandler) #创建一个TCP同步服务器
print "---waiting for connection----"
tcpServer.serve_forever() #开启工作狂模式
创建TCP客户端
#-*- coding:utf-8 -*-
from socket import *
HOST = "localhost"
PORT = 20000
ADDR = (HOST, PORT)
BUFSIZ = 1024
while True:
#因为服务器处理器默认行为是接收连接,得到请求,断开连接。因此要想多次发送会话,就必须重新建立socket
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
data = raw_input('>>>')
if not data:
break
#处理器类像文件一样处理Socket数据,因此行结束要自己添加\r\n
tcpCliSock.send("%s\r\n" % data)
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print data.strip() #去掉行结束符\r\n
tcpCliSock.close() #挂电话