23. Python脚本学习笔记二十三网络编程
本篇名言:“相处时需要包容,相恋时需要真心,争吵时沟通,孤独时需要人陪,难过时需要安慰,生气时需要冷静,快乐时需要分享。”
Python是一个很强大的网络编程工具,因为其内有很多常见网络协议的库,在库顶部可以获得抽象层。让我们可以集中精力在程序的逻辑处理上,而不是停留在网络实现的细节中。
1. 网络设计模块
1.1 Socket模块
网络编程中的一个基本组件就是套接字(socket).套接字包括两个:服务器套接字和客户机套接字。
一个套接字就是一个socket模块中的socket类的实例。实例化需要3个参数,第一个参数是地址族,第二个参数是流或数据报套接字,第三个参数是使用的协议。服务器套接字使用bind方法后,再调用listen方法去监听这个给定的地址。客户端套接字使用connect方法连接到服务器。
套接字有两个方法:send和recv。
看个实例:
服务器端:
import socket
s =socket.socket()
host =socket.gethostname()
port = 1234
s.bind((host,port))
s.listen(5)
while True:
c, addr = s.accept()
print 'Got connection from', addr
c.send('Thank you for connecting')
c.close()
客户机端:
importsocket
s = socket.socket()
host = socket.gethostname()
port = 1234
s.connect((host, port))
print s.recv(1024)
1.2 urllib和urllib2模块
在能使用的各种网络工作库中,功能最强大的是urllib和urllib2。这个模块能通过网络访问文件。两个模块差不读哦,不过urllib2更好一些。
通过如下2行代码,
from urllib import urlopen
webpage=urlopen('http://www.python.org')
可以获得网页的类文件对象。
使用如下代码
from urllib import urlopen, urlretrieve
urlretrieve('http://www.python.org','python_webpage.html')
将Pytohn主页保存到python_webapage.html文件中。
2. SocketServer
SocketServer模块是标准库中很多服务器框架的基础,这些服务器框架包括BaseHTTPServer,SimpleHTTPServer,CGIHTTPServer, SimpleXMLRPCServer和 DocXMLRPCServer等。
2.1 通过SocketServer框架
通过SocketServer来实现刚才的Socket,如下:
fromSocketServer 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.serve_forever()
这里多了一个请求处理程序Handler,每当客户端有一个请求时,就会实例化一个请求处理程序,并且各种处理方法会在处理请求时被调用。
3. 多连接
之前我们描述的都是一次连接一个客户机并处理请求。如何实现同时处理多个连接呢?
可以采用3种主要的方法:分叉(forking),线程(threading)以及异步IO(asynchronous I/O)。不过有几个缺点:1、分叉占据资源,2、线程处理能导致同步问题。
异步IO可以使用select函数来实现,在UNIX下也可以使用poll函数,poll函数的伸缩性更好,不过只能在UNIX系统中使用。
Select函数实现服务端如下:
import socket, select
s = socket.socket()
host = socket.gethostname()
port = 1234
s.bind((host, port))
s.listen(5)
inputs = [s]
while True:
rs,ws, es = select.select(inputs, [], [])
for rin rs:
ifr is s:
c, addr = s.accept()
print 'Got connection from', addr
inputs.append(c)
else:
try:
data = r.recv(1024)
disconnected = not data
except socket.error:
disconnected = True
if disconnected:
print r.getpeername(), 'disconnected'
inputs.remove(r)
else:
print data
4. Twisted
Twisted是一个事件驱动的Python网络框架,原来是为网络游戏开发的,现在被所有类型的网络软件使用了。
4.1 下载
https://twistedmatrix.com/trac/
从这个连接中进行下载并安装,即可。
再下载 zope.interface
https://pypi.python.org/pypi/zope.interface#downloads
将zope.interface-3.8.0-py2.7-win32.egg放到 C:\Python27\Scripts目录下。
在命令行中运行:
C:\>cd Python27\Scripts
C:\Python27\Scripts>easy_install.exe zope.interface-3.8.0-py2.7-win32.egg
4.2 编写Twisted服务器
在SocketServer的服务器有一个隐式的循环,在循环中服务器查找连接并为每个连接创建一个处理程序。
使用Twisted的简单服务器如下:
fromtwisted.internet importreactor
fromtwisted.internet.protocol importProtocol, Factory
class SimpleLogger(Protocol):
def connectionMade(self):
print'Got connection from', self.transport.client
def connectionLost(self,reason):
print self.transport.client, 'disconnected'
def dataReceived(self,data):
print data
factory = Factory()
factory.protocol = SimpleLogger
reactor.listenTCP(1234, factory)
reactor.run()
执行两个客户端并终端后输出如下:
Gotconnection from ('192.168.1.3', 51942)
Gotconnection from ('192.168.1.3', 51961)
('192.168.1.3',51961) disconnected
('192.168.1.3',51942) disconnected
这里必须实例化factory,还要设置它的protocol属性,这样在和客户机通信时就知道使用什么协议。然后在给定的端口处使用工厂进行监听,这个工厂要通过实例化协议对象来准备处理连接。使用reactor中的listenTCP函数来监听,最后调用模块中的run函数启动服务器。