Python 內置封裝了不少常見的網絡協議的庫,所以Python成爲了一個強大的網絡編程工具,這裏是對Python的網絡方面編程的一個簡單描述。html
在標準庫中有不少網絡設計相關的模塊,除了那些明確處理網絡事務的模塊外,還有不少模塊也是是和網絡相關的,下面是幾個經常使用的網絡設計模塊:python
socket
模塊是網絡編程中的基礎組件。socket 主要的做用就是做爲兩個程序之間的「通訊信道」,不一樣進程(不一樣主機)能夠經過socket相互發送信息,以達到網絡通訊的目的。socket 包括兩個部分:服務端和客戶端。服務端監聽端口號,等待客戶端發送的消息;而客戶端在須要發送信息是,鏈接服務端,將信息發送出去便可。下面是一個簡單的同步網絡編程的簡單示例:react
一個小型服務器:web
#Socket Server 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()
一個小型客戶端:編程
#Socket Client import socket s=socket.socket() host=socket.gethostname() port=1234 s.connect((host,port)) print s.recv(1024)
運行時,請將對應的端口(這裏是1234)添加到防火牆的InBound和OutBound的規則中。windows
urllib
和 urllib2
是Python標準庫中最強的的網絡工做庫。經過這兩個庫所提供的上層接口,使咱們能夠像讀取本地文件同樣讀取網絡上的文件。並且 urllib2
並非 urllib
的升級版本(應該是一種補充),兩者是不可相互替代的。服務器
經過使用 urllib
的 urlopen
函數能夠很容易的打開遠程的文件,以下:cookie
>>> from urllib import urlopen >>> webpage=urlopen('http://www.baidu.com') >>> text=webpage.readline(36) >>> print text <!DOCTYPE html><!--STATUS OK--><html >>>
也能夠經過在經過在路徑的前面添加 file:
來訪問本地文件:網絡
>>> from urllib import urlopen >>> webpage=urlopen(r'file:f:\python\myDemo\game.txt') >>> txt=webpage.read() >>> print txt 蛋蛋 1 10 10 >>>
你還能夠經過 urllib
提供的 urlretrieve
函數,來直接保存遠程文件副本:多線程
>>> from urllib import urlretrieve >>> webpage=urlretrieve('http://www.baidu.com','f:\python\myDemo\webpage.html') >>> print type(webpage) <type 'tuple'> >>>
除了 socket、urllib和urllib2這些模塊之外標準庫還有不少和網絡相關的模塊,下面的列表是其中的一部分:
=========================================================== 模塊 描述 =========================================================== asynchat asyncore的加強版本 asyncore 異步socket處理程序 cgi 基本的CGI支持 Cookie Cookie對象操做,主要用於服務器操做 cookielib 客戶端cookie支持 email E-mail消息支持(包括MIME) ftplib FTP客戶端模塊 gopherlib gopher客戶端博客 httplib HTTP客戶端模塊 imaplib IMAP4客戶端模塊 mailbox 讀取幾種郵件的格式 mailcap 經過mailcap文件訪問MIME配置 mhlib 訪問MH郵箱 nntplib NNTP客戶端模塊 poplib POP客戶端模塊 robotparser 支持解析Web服務器的robot文件 SimpleXMLRPCServer 一個簡單的XML-RPC服務器 stmpd SMTP服務器模塊 smtplib SMTP客戶端模塊 telnetlib Telnet客戶端模塊 urlparse 支持解析URL xmlrpclib XML-RPC的客戶端支持
SocketServer模塊是標準庫中不少其餘服務器框架的基礎,這些服務器框架包括:BaseHTTPServer、SimpleHTTPServer、CGIHTTPServer、SimpleXMLRPCServer和DocXMLRPCServer,這些服務框架都是在基礎框架上增長了特定的功能。SocketServer包含了4個基本的類:
下面是一個基於SocketServer的簡單Socket Server端示例:
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()
通常狀況下Socket中的Client端經常不止一個,想要使Socket Server端能同時處理多個Client的鏈接通常由三種主要的方法:
分叉(fork)是一個UNIX術語;當分叉一個進程(一個運行的程序)時,基本上時複製了它,而且分叉後的兩個進程都從當前執行的點繼續運行,而且每一個進程都有本身的內存副本。一個進程(開始的那個)成爲另外一個進程的(複製的,也就是子進程)的父進程。在一個使用分叉的服務器中,每一個客戶端鏈接都利用分叉建立一個子進程。父進程繼續監聽鏈接,同時子進程處理客戶端。當客戶端的請求結束時,子進程退出。分叉的進程是並行執行的,客戶端直接沒必要相互等待。分叉的缺點是比較耗費資源(每一個分叉出來的進程都須要本身的內存)。下面是一個使用分叉建立Socket服務端的示例(使用了分叉(fork),Windows系統不支持):
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=TCPServer(('',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=TCPServer(('',1234),handler) server.serve_forever()
在Python中的異步I/O的基礎就是 select
模塊的 select
函數。標準庫中的 asyncore
和 asynchat
模塊對它們進行了進一步的包裝,能夠從更高層次來處理異步I/O。poll
函數和 select
函數同樣,也屬於 select
模塊,這兩個函數的功能基本同樣,相對而言 poll
的伸縮性更好,但其職能在UNIX系統使用使用。
select
函數須要3個序列做爲它的必選參數(輸入、輸出、異常狀況),第四個參數是可選的,表示以秒爲單位的超時時間。下面是一個使用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 r in rs: if r is s: c,addr=s.accept() print 'Got connection from ',addr imputs.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
poll
方法比 select
使用起來簡單,下面的時候就是上面示例的 poll
版本:
import socket,select s=socket.socket() host=socket.gethostname() port=1234 s.bind((host,port)) fdmap={s.fileno():s} s.listen(5) p=select.poll() p.register(s) while True: events=p.poll() for fd,event in events: if fd in fdmap: c,addr=s.accept() print 'Got connection from ',addr p.register(c) fdmap[c.fileno()]=c elif event & select.POLLIN: data=fdmap[fd].recv(1024) if not data: print fdmap[fd].getpeername(),'disconnected' p.unregister(fd) del fdmap[fd] else: print data
Twisted是用Python實現的基於事件驅動的網絡引擎框架。
(參考資料:http://blog.csdn.net/hanhuili/article/details/9389433)。
windows下,能夠直接下載安裝進行安裝 https://twistedmatrix.com/trac/wiki/Downloads
到此彷佛安裝成功了,但在使用twisted時,即引入twisted時, 如:from twisted.internet.protocol import Protocol,ClientFactory
運行時會提示 ImportError: Twisted requires zope.interface 3.6.0 or later: no module named
因此還須要安裝zope包,直接下載安裝便可
https://pypi.python.org/pypi/zope.interface#downloads
from twisted.internet import reactor from twisted.internet.protocol import Protocol,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()
使用LineReceiver協議改進的記錄服務器:
from twisted.internet import reactor from twisted.internet.protocol import Factory from twisted.protocol.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,line): print line factory=Factory() factory.protocol=SimpleLogger reactor.listenTCP(1234,factory) reactor.run()