Python是个很强大的网络编程工具,原因有二:
1. python内有很多针对常见网络协议的库
2. Python在处理字节流方面的优势
本章主要内容: 探讨Python标准库中的一些网络模块,探讨SocketServer类,最后是Twisted框架.
相关模块
Socket模块
基本组件,用于两个程序之间的信息通道。套接字包括两个: 服务器套接字和客户端套接字。创建一个服务器套接字后,让它等待连接,这样它就在某个网络地址处监听。客户端套接字负责:简单的连接,完成事务,断开连接。一个套接字就是一个socket模块中的socket类的实例。它的实例化需要3个参数:
第一个参数: 地址族,默认是socket.AF_INET
第二个参数: 流(socket.SOCK_STREAM)或数据报(socket.SOCK_DGRAM)
第三个参数: 使用的协议,默认是0,使用默认值即可。对于一个普通的套接字,不需要提供任何参数
服务器套接字使用bind方法后,再调用listen方法监听给定的地址,客户端套接字使用connect去连服务器。一个地址就是一个格式化元祖(host,port).listen方法只有一个参数,即服务器未处理的连接长度(即允许排队等待的连接数目,这些连接在停止接收之前等待接收).
服务器套接字开始监听后,它就可以接受客户端的连接。这个步骤使用accept方法完成。这个方法会阻塞(等待),直到客户端连接,然后返回一个格式为(client,address)的元祖,client:客户端套接字,address:一个前面解释过的地址。服务器能处理客户端到它满意的程度,然后调用另一个accept方法开始等待下一个连接。这个过程通常都在一个无限循环中实现的。套接字有两个方法:send和recv,用于传输数据.
最简单的CLIENT/SERVER
服务器端程序
- import socket
-
- s = socket.socket()
-
- host = socket.gethostname()
- port = 1234
-
- s.listen(5)
- while True:
- c.addr =s.accept()
- print 'Got connect from',addr
- c.send('Thank you for connecting')
- c.close()
客户端程序
- import socket
-
- s = socket.socket()
-
- host = socket.gethostname()
- port = 1234
-
- s.connect((host,port))
- print s.recv(1024)
urllib和urllib2模块
网络库中,最强大的是urllib和urllib2.这两个模块功能差不多,但urllib2更好一些。如果只使用简单的下载,urllib就足够了。如果需要使用HTTP验证或cookie或者要为自己的协议写扩展程序的话,那么urllib2是个最好的选择.
1. 打开远程文件
#可以使用只读模式,使用的是来自urllib莫开的urlopen,而不是open或file
- >>> from urllib import urlopen
- >>> webpage = urlopen('http://www.python.org')
#urlopen返回的类文件对象支持close,read,readline,readlines,也支持迭代。
假设想要提取Python页中"About"链接的URL,那么就可以用正则表达式来实现.
- >>> import re
- >>> text = webpage.read()
- >>> m = re.search('<a href="([^"]+).*?">about</a>',text,re.IGNORECASE)
- >>> m.group(1)
- '/about/'
2. 获取远程文件
如果希望urllib为你下载文件并在本地存储一个文件的副本,那么可以使用urlretrieve. 它返回一个元祖(filename,headers)而不是类文件对象,filename是本地文件的名字,headers包含一些远程文件的信息,如果想要为下载的副本指定文件名,可以在urlretrieve函数的第2个参数中给出。
>>> urlretrieve('http://www.python.org','C:\\python_webpage.html')
#该语句获取Python的主页并把它存储在文件python_webpage.html中,如果没有指定,文件会放在临时的位置,用open函数打开它,完成操作后,删除以节省磁盘空间。要清理临时文件,可以用urlcleanup函数,该函数负责清理工作.
其他模块
SocketServer
如果想实现超出基础的应用,就要借助SocketServer,该模块是很多服务器框架的基础,包括BaseHTTPServer,SimpleHTTPServer,CGIHTTPServer,SimpleXMLRPCServer和DocXMLRPCServer.
SocketServer包含了4个基本的类:
针对TCP套接字流的TCPServer
针对UDP数据报套接字的UDPServer
针对UnxiStreamServer
针对UnixDatagramServer
主要用的第一个类。
代码清单: 一个基于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.serve_forever()
多连接:
一次处理多个连接的3个方法: 分叉(forking)、线程(threading)以及异步I/O(asynchronous I/O)
代码清单: 使用了分叉技术的服务器
- from SocketServer import TCPServer, ForkingMixIn, StreamRequestHandler
-
- class Server(ForkingMixIn,TCPServer): pass
-
- class Handler(StreamRequestHandler):
-
- def handle(self):
- addr = self.request.getpeername()
- print 'Got connection from', addr
- self.wfile.write('Thank you for connecting')
-
- server = Server(('',1234),Handler)
- server.serve_forever()
代码清单: 使用了线程处理的服务器
- 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 connecting')
-
- server = Server(('',1234),Handler)
- server.serve_forever()
Twisted
来自于Twisted Matrix实验室的Twisted是一个事件驱动的Python的网络框架,原来是为了网络游戏开发的,现在被所有类型的网络软件使用。Twisted能很好地和几个常见的GUI工具包(Tk,GTK,Qt以及wxWidgets)协同工作。Twisted是一个非常丰富的框架,并且支持WEB服务器,客户机,SSH2,SMTP,POP3,IMAP4,AIM,ICQ,IRC,MSN,DNS等.
安装Twisted
下载网址:https://twistedmatrix.com/trac/ 可以选择自己的操作系统,Python的版本来安装.
在Windows平台下,可选择.msi或.exe文件来安装,也可以用Distutils来安装python setup.py install
其他的平台系统,可选择RPM,APT,Portage等,来安装
编写Twisted服务器
代码清单: 使用Twisted的简单服务器
- from twisted.internet import reactor
- from twisted.internet.protocol import Protocol, Factory
-
- class SimpleLogger(Protocol):
-
- def connectionMade(self):
- print 'Got connection from', self.transfort.client
-
- def connectionLost(self,reason):
- print self.transport.client, 'disconnected'
-
- def dataReceived(self, data):
- print data
-
- factory = Factory()
- factory.protocal = SimpleLogger
代码清单: 使用了LineReceiver协议改进的记录服务器
- from twisted.internet import reactor
- from twisted.internet.protocol import Factory
- from twisted.protocols.basic import LineReceiver
-
- class SimpleLogger(LineReceiver):
-
- def connectionMade(self):
- print 'Got connection from', self.transport.client
-
- def connectionLost(self, reason):
- print self.transport.client, 'disconnected'
-
- def lineReceived(self, reason):
- print line
-
- factory = Factory()
- factory.protocol = SimpleLogger
-
- reactor.listenTCP(1234, factory)
- reactor.run()