【循序渐进学Python】15.网络编程
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.cnblogs.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.cnblogs.com/IPrograming/','C:\\temp.html')
print type(webpage) # <type 'tuple'>
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 = [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 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.cnblogs.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】15.网络编程的更多相关文章
- python基础网络编程--转
python之网络编程 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的 ...
- python之网络编程
本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用 ...
- Python的网络编程--思维导图
Python的网络编程--思维导图
- Python高级网络编程系列之第一篇
在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握 ...
- python 基础网络编程2
python 基础网络编程2 前一篇讲了socketserver.py中BaseServer类, 下面介绍下TCPServer和UDPServer class TCPServer(BaseServer ...
- python 基础网络编程1
python 基础网络编程1 Source code: Lib/socketserver.py lib的主目录下有一个sockserver.py文件, 里面是python基本的网络编程模型 共有一个b ...
- Python Socket 网络编程
Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...
- python中网络编程基础
一:什么是c\s架构 1.c\s即client\server 客户端\服务端架构. 客户端因特定的请求而联系服务器并发送必要的数据等待服务器的回应最后完成请求 服务端:存在的意义就是等待客户端的请求, ...
- Python Socket 网络编程 (客户端的编程)
Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...
随机推荐
- Design1:数据层次结构建模之一
1,在现实世界中,有很多现象存在层次结构,公司的人事职称是典型的层次结果,如下图 Sql Server是关系型DB,适合存储二维关系的数据,如何存储具有层次结构的数据了?需要使用一个字段ParentI ...
- Js杂谈-正则的测试与回溯次数
例子来源于<精通正则表达式(第三版)>这本书,我贴出来: 这里的NFA是正则的一种引擎,书中介绍了一共三种引擎:NFA,DFA和POSIX NFA.像一般我们常用的.NET,java.ut ...
- Kruskal算法(一)之 C语言详解
本章介绍克鲁斯卡尔算法.和以往一样,本文会先对克鲁斯卡尔算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 最小生成树 2. 克鲁斯卡尔算法介绍 3 ...
- PHP的学习--PHP的闭包
php的闭包(Closure)也就是匿名函数,是PHP5.3引入的. 闭包的语法很简单,需要注意的关键字就只有use,use是连接闭包和外界变量. $a = function() use($b) {} ...
- 什么是WeakHashMap--转
原文地址:http://laravel.iteye.com/blog/2303244 Java WeakHashMap 到底Weak在哪里,它真的很弱吗?WeakHashMap 的适用场景是什么,使用 ...
- Quartz Java resuming a job excecutes it many times--转
原文地址:http://stackoverflow.com/questions/1933676/quartz-java-resuming-a-job-excecutes-it-many-times Q ...
- [Node.js] DSL in action
原文地址:http://www.moye.me/2015/05/30/dsl-in-action/ 最近看了本有意思的书,受到了一些启发,在此记录一下: DSLs in action DSL是什么 ...
- 在Python中实现PageFactory模式
关于 PageFactory 的概念主要是Java中内置了PageFactory类. import org.openqa.selenium.support.PageFactory; …… 例子,htt ...
- Testing - 测试基础 - 阶段
估算 测试对软件工作量的估算的准确性 测试评估软件系统的状况的准确性 关注点: 不准确的估算 不适当的开发过程 不真实的状态报告 如何知道对工作量的估算是正确的 估算工作量的工具很容易出错 对软件工作 ...
- Struts+Hibernate+Spring实现用户登录功能
通过登录案例实现三大框架之间的整合,登录功能是任何系统和软件必不可少的一个模块,然而通过这个模块来认识这些复杂的框架技术,理解数据流向和整个设计思路是相当容易的.只有在掌握了这些小模块的应用后,才能轻 ...