设为首页 收藏本站
查看: 1040|回复: 0

[经验分享] 【循序渐进学Python】15.网络编程

[复制链接]

尚未签到

发表于 2015-4-19 05:47:14 | 显示全部楼层 |阅读模式
  Python 内置封装了很多常见的网络协议的库,因此Python成为了一个强大的网络编程工具,这里是对Python的网络方面编程的一个简单描述。

1. 常用的网络设计模块
  在标准库中有很多网络设计相关的模块,除了那些明确处理网络事务的模块外,还有很多模块也是是和网络相关的,下面是几个常用的网络设计模块:

1.1 socket 模块
  socket 模块是网络编程中的基础组件。socket 主要的作用就是作为两个程序之间的“通信信道”,不同进程(不同主机)可以通过socket相互发送信息,以达到网络通信的目的。socket 包括两个部分:服务端和客户端。服务端监听端口号,等待客户端发送的消息;而客户端在需要发送信息是,连接服务端,将信息发送出去即可。下面是一个简单的同步网络编程的简单示例:
  这是Socket Server 部分:
  

import socket  

  
s = socket.socket()
  

  
host = socket.gethostname()
  
port = 8088
  
s.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 socket  

  
s = socket.socket()
  

  
host = socket.gethostname()
  
port = 8088
  

  
s.connect((host,port))
  
print s.recv(1024)
  

  运行时,请将对应的端口(这里是8088)添加到防火墙的InBound和OutBound的规则中。

1.2 urllib 和 urllib2 模块
  urllib 和 urllib2 是Python标准库中最强的的网络工作库。通过这两个库所提供的上层接口,使我们可以像读取本地文件一样读取网络上的文件。而且 urllib2 并不是 urllib 的升级版本(应该是一种补充),二者是不可相互替代的。
  通过使用 urllib 的 urlopen 函数可以很容易的打开远程的文件,如下:
  

from urllib import urlopen  

  
webpage = urlopen('http://www.iyunv.com/IPrograming/')
  
txt = webpage.readline(45)
  
print txt  # !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
  

  也可以通过在通过在路径的前面添加 file: 来访问本地文件:
  

from urllib import urlopen  

  
webpage = urlopen(r'file:D:\H\sr23upd\ADD_ABBR.txt')
  
txt = webpage.readline(45)
  
print txt
  

  如果你还可以通过 urllib 提供的 urlretrieve函数,来直接保存远程文件副本:
  

from urllib import urlretrieve  

  
webpage = urlretrieve('http://www.iyunv.com/IPrograming/','C:\\temp.html')
  
print type(webpage) #
  

1.3 其他与网络相关的模块
  除了 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的客户端支持                 
  

2. SocketServer
  SocketServer模块是标准库中很多其他服务器框架的基础,这些服务器框架包括:BaseHTTPServer、SimpleHTTPServer、CGIHTTPServer、SimpleXMLRPCServer和DocXMLRPCServer,这些服务框架都是在基础框架上增加了特定的功能。SocketServer包含了4个基本的类:


  • TCPServer,针对TCP的Socket  

  • UDPServer,针对UDP数据报的Socket  

  • UnixStreamServer  

  • UnixDatagramServer
  下面是一个基于SocketServer的简单Socket Server端示例:
  

from SocketServer import TCPServer, StreamRequestHandler  

  
class Handler(StreamRequestHandler):
  

  def handle(self):
  addr = self.request.getpeername()
  self.wfile.write('Thank you for connectiong')
  

  
server = TCPServer(('',8088),Handler)
  
server.serve_forever()
  

3. 多连接
  一般情况下Socket中的Client端常常不止一个,想要使Socket Server端能同时处理多个Client的连接一般由三种主要的方法:


  • 分叉(forking)(windows 不支持)  

  • 线程(threading)  

  • 异步I/O(asynchronous I/O)
3.1 使用分叉
  分叉(fork)是一个UNIX术语;当分叉一个进程(一个运行的程序)时,基本上时复制了它,并且分叉后的两个进程都从当前执行的点继续运行,并且每个进程都有自己的内存副本。一个进程(开始的那个)成为另一个进程的(复制的,也就是子进程)的父进程。在一个使用分叉的服务器中,每个客户端连接都利用分叉创建一个子进程。父进程继续监听连接,同时子进程处理客户端。当客户端的请求结束时,子进程退出。分叉的进程是并行执行的,客户端直接不必相互等待。分叉的缺点是比较耗费资源(每个分叉出来的进程都需要自己的内存)。下面是一个使用分叉创建Socket服务端的示例:
  

# --coding:utf-8--  
# 使用了分叉(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 connectiong')
  

  
server = Server(('',1234),Handler)
  
server.serve_forever()
  

3.2 使用线程
  线程是轻量级的进程或子进程,所有的线程都存在于相同的进程(一个运行的程序)中,且共享内存。虽然使用多线程相对于分叉占用的资源较少,但是由于共享内存,所有必需要确保它们的变量不会冲突,或者是同一时间修改同一内容,这样会造成混乱。这些问题可以归结为同步问题。下面是使用多线程的一个简单示例:
  

# --coding:utf-8--  
# 使用多线程
  
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 connection')
  

  
server = Server(('',1234),Handler)
  
server.serve_forever()
  

3.3 带有 select 和 poll 的异步I/O
  在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 =
  
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 data
  

  poll 方法比 select 使用起来简单,下面的时候就是上面示例的 poll 版本:
  

# -- coding: utf-8 --  
# Windows 系统不支持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
  

4. 使用Twisted
  Twisted 是一个事件驱动的Python网络框架。使用 Twisted 框架首先需要单独下载安装。我们可以使用pip包管理工具来进行安装,参考:http://www.iyunv.com/IPrograming/p/Python_module_package.html#pip。下面是使用Twisted的两个简单示例:

4.1 使用 Twisted
  

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.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,line):
  print line
  

  
factory = Factory()
  
factory.protocol = SimpleLogger
  

  
reactor.listenTCP(1234, factory)
  
reactor.run()
  

参考资料&进一步阅读
  Python基础教程(第二版)
  Twisted

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-58456-1-1.html 上篇帖子: Python深入05 装饰器 下篇帖子: Python基础03 序列
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表