Python 內置封裝了很多常見的網絡協議的庫,因此Python成為了一個強大的網絡編程工具,這里是對Python的網絡方面編程的一個簡單描述。
在標準庫中有很多網絡設計相關的模塊,除了那些明確處理網絡事務的模塊外,還有很多模塊也是是和網絡相關的,下面是幾個常用的網絡設計模塊:
socket 模塊是網絡編程中的基礎組件。socket 主要的作用就是作為兩個程序之間的“通信信道”,不同進程(不同主機)可以通過socket相互發送信息,以達到網絡通信的目的。socket 包括兩個部分:服務端和客戶端。服務端監聽端口號,等待客戶端發送的消息;而客戶端在需要發送信息是,連接服務端,將信息發送出去即可。下面是一個簡單的同步網絡編程的簡單示例:
這是Socket Server 部分:
import sockets = socket.socket()host = socket.gethostname()port = 8088s.bind((host,port))s.listen(5)while True: c, addr = s.accept() PRint 'Got connection from', addr c.send('Thank you for connection') c.close()這是Socket Client 部分:
import sockets = socket.socket()host = socket.gethostname()port = 8088s.connect((host,port))print s.recv(1024)運行時,請將對應的端口(這里是8088)添加到防火墻的InBound和OutBound的規則中。
urllib 和 urllib2 是Python標準庫中最強的的網絡工作庫。通過這兩個庫所提供的上層接口,使我們可以像讀取本地文件一樣讀取網絡上的文件。而且 urllib2 并不是 urllib 的升級版本(應該是一種補充),二者是不可相互替代的。
通過使用 urllib 的 urlopen 函數可以很容易的打開遠程的文件,如下:
from urllib import urlopenwebpage = urlopen('http://m.survivalescaperooms.com/iprograming/')txt = webpage.readline(45)print txt # !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 也可以通過在通過在路徑的前面添加 file: 來訪問本地文件:
from urllib import urlopenwebpage = urlopen(r'file:D:/H/sr23upd/ADD_ABBR.txt')txt = webpage.readline(45)print txt 如果你還可以通過 urllib 提供的 urlretrieve函數,來直接保存遠程文件副本:
from urllib import urlretrievewebpage = urlretrieve('http://m.survivalescaperooms.com/IPrograming/','C://temp.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, StreamRequestHandlerclass Handler(StreamRequestHandler): def handle(self): addr = self.request.getpeername() self.wfile.write('Thank you for connectiong')server = TCPServer(('',8088),Handler)server.serve_forever()一般情況下Socket中的Client端常常不止一個,想要使Socket Server端能同時處理多個Client的連接一般由三種主要的方法:
分叉(fork)是一個UNIX術語;當分叉一個進程(一個運行的程序)時,基本上時復制了它,并且分叉后的兩個進程都從當前執行的點繼續運行,并且每個進程都有自己的內存副本。一個進程(開始的那個)成為另一個進程的(復制的,也就是子進程)的父進程。在一個使用分叉的服務器中,每個客戶端連接都利用分叉創建一個子進程。父進程繼續監聽連接,同時子進程處理客戶端。當客戶端的請求結束時,子進程退出。分叉的進程是并行執行的,客戶端直接不必相互等待。分叉的缺點是比較耗費資源(每個分叉出來的進程都需要自己的內存)。下面是一個使用分叉創建Socket服務端的示例:
# --coding:utf-8--# 使用了分叉(fork),Windows系統不支持from SocketServer import TCPServer, ForkingMixIn, StreamRequestHandlerclass Server(ForkingMixIn, TCPServer):passclass Handler(StreamRequestHandler): def handle(self): addr = self.request.getpeername() print 'Got connection from', addr self.wfile.write('Thank you for connectiong')server = Server(('',1234),Handler)server.serve_forever()線程是輕量級的進程或子進程,所有的線程都存在于相同的進程(一個運行的程序)中,且共享內存。雖然使用多線程相對于分叉占用的資源較少,但是由于共享內存,所有必需要確保它們的變量不會沖突,或者是同一時間修改同一內容,這樣會造成混亂。這些問題可以歸結為同步問題。下面是使用多線程的一個簡單示例:
# --coding:utf-8--# 使用多線程from SocketServer import TCPServer, ThreadingMixIn, StreamRequestHandlerclass Server(ThreadingMixIn,TCPServer):passclass Handler(StreamRequestHandler): def handle(self): addr = self.request.getpeername() print 'Got connection from', addr self.wfile.write('Thank you for connection')server = Server(('',1234),Handler)server.serve_forever()在Python中的異步I/O的基礎就是 select 模塊的 select 函數。標準庫中的 asyncore 和 asynchat 模塊對它們進行了進一步的包裝,可以從更高層次來處理異步I/O。poll 函數和 select 函數一樣,也屬于 select 模塊,這兩個函數的功能基本一樣,相對而言 poll 的伸縮性更好,但其職能在UNIX系統使用使用。
select 函數需要3個序列作為它的必選參數(輸入、輸出、異常情況),第四個參數是可選的,表示以秒為單位的超時時間。下面是一個使用 select 的簡單示例:
import socket, selects = socket.socket()host = socket.gethostname()port = 1234s.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 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 datapoll 方法比 select 使用起來簡單,下面的時候就是上面示例的 poll 版本:
# -- coding: utf-8 --# Windows 系統不支持pollimport socket, selects = socket.socket()host = socket.gethostname()port = 1234s.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 dataTwisted 是一個事件驅動的Python網絡框架。使用 Twisted 框架首先需要單獨下載安裝。我們可以使用pip包管理工具來進行安裝,參考:http://m.survivalescaperooms.com/IPrograming/p/Python_module_package.html。下面是使用Twisted的兩個簡單示例:
from twisted.internet import reactorfrom twisted.internet.protocol import Protocol, Factoryclass 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 datafactory = Factory()factory.protocol = SimpleLoggerreactor.listenTCP(1234,factory)reactor.run()使用LineReceiver協議改進的版本:
from twisted.internet import reactorfrom twisted.internet.protocol import Factoryfrom twisted.protocols.basic import LineReceiverclass 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 linefactory = Factory()factory.protocol = SimpleLoggerreactor.listenTCP(1234, factory)reactor.run()新聞熱點
疑難解答