| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> Python基础教程(第2版)第十四章 网络编程 -> 正文阅读 |
|
[系统运维]Python基础教程(第2版)第十四章 网络编程 |
1.网络设计模块1.1 socket模块套接字(socket)主要是两个程序之间的“信息通道”,程序可能(通过网络连接)分布在不同的计算机上通过套接字相互发送信息 一个套接字就是一个socket模块中的socket类的实例,它的实例化需要3个参数 ????????第1个参数是地址族(默认是socket.AF_ INET) ????????第2个参数是流 (socket.SOCK_STREAM,默认值)或数据报(socket.SOCK_DGRAM)套接字 ????????第3个参数是使用的协议(默认是0,使用默认值即可) ????????对于一个普通的套接字,不需要提供任何参数 1.1.1 服务器套接字(同步网络编程)????????服务器必须准备随时处理客户端的连接,同时还要处理多个连接 ????????创建一个服务器套接字后,让它等待连接,它就会在某个网络地址 (IP地址和端口号的组合)处监听 ????????服务器端套接字使用bind方法后,再调用listen方法去监听给定的地址 ????????????????地址:一个格式为(host, port)的元组,host是主机名, port是端口号(一个整数) ????????????????listen方法只有一个参数:服务器未处理的连接的长度(即允许排队等待的连接数目,这些连接在停止接收之前等待接收) ????????服务器端套接字开始监听后,它就可以接受客户端的连接,这个步骤使用accept方法来完成 ????????????????accept方法会阻塞(等待)直到客户端连接,然后该方法就返回一个格式为 (client, address)的元组,client是一个客户端套接字,address是一个前面解释过的地址 ????????????????服务器能处理客户端到它满意的程度,然后调用另一个accept方法开始等待下一个连接 1.1.2 客户端套接字????????处理客户端套接字通常比处理服务器端套接字容易,因为客户机只是简单地连接,完成事务,断开连接 ????????客户端套接字使用connect方法连接到服务器(connect方法中的地址与bind中的地址相同) 1.1.3 套接字方法send:使用字符串参数调用send以发送数据 revc:使用一个所需的(最大)字节数做参数调用recv来接收数据,如果不能确定使用哪个数
能在服务器还在运行时运行多个客户机,通过用服务器端所在机器的实际主机名来代替客户端调用gethostname所得到的主机名,就可以让两个运行在不同机器上的程序通过网络连接起来 1.2 urllib和urllib2模块通过一个简单的函数调用,几乎可以把任何URL指向的东西用做程序的输人,即能通过网络访问文件,就像那些文件存在于你的电脑上一样 如果只使用简单的下载,urllib就足够了 ? ? ? ? 使用urllib模块的urlopen,可以像打开本地文件一样打开远程文件,不同的是可以使用只读模式(也可以以file开头的URL访问本地文件) ????????urlopen返回的是一个能从中读取数据的类文件对象,该对象支持close、read、readline、readlines和迭代
????????如果想提取前面打开的Python页中“ About”链接的 (相对)URL,可以用正则表达式实现?
如果希望urllib为你下载文件并在本地文件中存储一个文件的副本,那么可以使用urlretrieve ????????urlretrieve返回一个元组 (filename,headers)而不是类文件对象,filename是本地文件的名宇(由urllib自动创建),headers包含一些远程文件的信息 ????????如果想要为下载的副本指定文件名,可以在urlretrieve函数的第2个参数中给出
????????如果没有指定文件名,文件就会放在临时的位置,用open函数可以打开它,但如果完成了对它的操作,就可以删除它以节省硬盘空间 ????????要清理临时文件,可以调用urlcleanup函数,但不要提供参数,该函数会负责清理工作 如果需要使用HTTP验证 (HTTP authentication) 或cookie或者要为自己的协议写扩展程序的 1.3其他模块2.SocketSever和它的朋友们SocketServer模块是标准库中很多服务器框架的基础,这些服务器框架都为基础服务器增加了特定的功能 ????????BaseHTTTPServer、SimpleHTTPServer、 CGIHTTPServer、SimpleXMLRPCServer、 SocketServer包含了4个基本的类:针对 TCP套接字流的TCPServer,针对UDP数据报套接字 写一个使用SocketServer框架的服务器时,大部分代码会在一个请求处理程序中 ????????每当服务器收到一个来自客户端的请求时,就会实例化一个请求处理程序,此时它的各种处理方法会在处理请求时被调用,具体调用哪个方法取决于特定的服务器和使用的处理程序类 ????????这样可以把它们子类化,使得服务器调用自定义的处理程序集 ????????基本的BaseRequestHandler类把所有的操作都放到了处理器的一个叫做handle的方法中,这个方法会被服务器调用,这个方法就会访问属性self.request中的客户端套接字(如果使用的是流,那么可以使用StreamRequestHandler类,这个类创建了两个新属性:self.rfile用于读取和self. wfile用于写入),然后就能使用这些类文件对象和客户机进行通信 SocketServer框架中的其他类实现了对HTTP服务器的基本支持,其中包括运行CGI脚本,包括对XML RPC(在第27章讨论)的支持
????????StreamRequestHandler在连接处理完后会负责关闭连接? 3.多连接目前为止讨论的服务器解决方案都是同步的:即一次只能连接一个客户机并处理它的请求。如果每个请求只是花费很少的时间,比如一个完整的聊天会话,那么同时能处理多个连接就很重要 有三种主要的方法能实现这个目的:分叉(forking)、线程(threading)以及异步I/O 通过对SocketServer服务器使用mix-in类,派生进程和线程很容易处理。即使要自己实现它们,这些方法也很容易使用 ????????同时,它们也有缺点:分叉会占据资源,并且如果有太多的客户端时分叉不能很好分叉 ????????尽管如此,对于合理数量的客户端,分叉在现代的UNIX或者Linux系统中是很高效的,如果有一个多CPU系统,那效率会更高 3.1 使用SocketSever进行分叉和线程处理分叉是一个UNIX术语,当分叉一个进程(一个运行的程序)时,基本上是复制了它,并且分叉后的两个进程都从当前的执行点继续运行,每个进程都有自己的内存副本 (比如变量) ????????原来的进程称为父进程,复制的进程称为子进程 ????????在一个使用分叉的服务器中,每一个客户端连接都利用分叉创造一个子进程 ????????父进程继续监听新的连接,子进程处理客户端,当客户端的请求结束时,子进程就退出了 ????????分叉的进程是并行运行的,客户端之间不必互相等待
因为分叉有点耗费资源(每个分叉出来的进程都需要自己的内存),这就存在了另一个选择:线程 ????????线程是轻量级的进程或子进程,所有的线程都存在于相同的(真正的)进程中,共享内存? ? ? ?????????资源消耗的下降伴随着一个缺陷:因为线程共享内存,所以必须确保它们的变量不会冲突,或者是在同一时间修改同一内容,这会造成混乱,这些问题都可以归结为同步问题 在现代操作系统中(除了Windows,它不支持分叉),分叉实际是很快的,现代的硬件能比以往更好地处理资源消耗,如果不想被同步问题所困扰,分叉是一个很好的选择
避免线程和分叉的另外一种方法是转换到Stackless Python,一个为了能够在不同的上下文之间快速、方便切换而设计的Python版本 ????????它支持一个叫做微线程(microthreads)的类线程的并行形式,微线程比真线程的伸缩性要好 3.2 带有select和poll的异步I/O异步I/O在底层的实现有点难度,基本的机制是select模块的select函数 ? ? ? ? 还存在更高的层次处理异步I/O的框架,这为处理一个强大可伸缩的机制提供了一个简单的、抽象的接口 ????????包含在标准库中的这种类型的基本框架由asyncore和asynchat模块组成 ????????Twisted是一个非常强大的异步网络编程框架 当一个服务器与一个客户端通信时,来自客户端的数据可能是不连续的,我们可以只处理在给定时间内真正要进行通信的客户端:不需要一直监听,只要监听一会,然后把它放在其他客户端的后面 上述功能的基础是来自select模块的select函数和poll函数(poll的伸缩性更好,但它只能在UNIX系统中使用) 3.2.1?select函数select函数需要3个序列(文件描述符整数)作为它的必选参数,此外还有一个可选的以秒为单位的超时时间作为第4个参数 ? ? ? ? 3个序列用于输入、输出以及异常情况 ?????????序列能包含文件对象(在Windows中行不通)或者套接字 ????????如果没有给定超时时间,select会处于等待状态,直到其中的一个文件描述符已经为行动做好了准备 ????????如果给定了超时时间,select最多阻塞给定的超时时间,如果给定的超时时间是0,那么就给出一个连续的poll ????????select的返回值是3个序列(也就是一个长度为3的元组),每个代表相应参数的一个活动子集,如返回的第1个序列是一个输入文件描述符的序列,其中有一些可以读取的东西
3.2.2 poll函数?poll方法使用起来比select简单,在调用poll时,会得到一个poll对象 ????????可以使用poll对象的register方法注册一个文件描述符(或者是带有fileno方法的对象) ????????注册后可以使用unregister方法移除注册的对象 ????????注册了一些对象(比如套接字)以后,就可以调用poll方法(带有一个可选的超时时间参数)并得到一个(fd,event)格式列表(可能是空的) ????????fd是文件描述符 ????????event会告诉你发生了什么,它是一个位掩码(整数),这个整数的每个位对应不同的事件,那些不同的事件是select模块的常量,为了验证一个给定的事件是否发生了,可以使用按位与操作符(&):if event & select.POLLIN : ...???????? ?
4.Twisted来自于Twisted Matrix实验室的Twisted是一个事件驱动的Python网络框架,原来是为网络游戏开发的,现在被所有类型的网络软件使用 在Twisted中,需要实现事件处理程序,事件处理程序在一个协议中定义,在一个新的连接到达时,同样需要一个创建这种协议对像的工厂 但如果只是想要创建一个通用的协议类的实例,那么就可以使用Twited自带的工厂(factory类在twisted.internet.protocol模块中) 当编写自己的协议时,要使用和超类一样的模块中的protocol ????????得到了一个连接后,事件处理程序connectionMade就会被调用 ????????丢失了一个连接后,connectionLost就会被调用 ????????来自客户端的数据是通过处理程序dataReceived接收的 ? ? ? ? 如果想要使用事件处理策略来把数据发回到客户端,可以使用对象self.transport,这个对象有一个write方法,也有一个包含客户机地址(主机名和端口号)的client属性
twisted.protoccls.basic模块中包含一个有用的预定义协议LineReceiver,它实现了dataReceived 并且只要收到了一整行就调用事件处理程序lineReceived 如果要在接受数据时做些事情,可以使用由LineReceiver定义的叫做rawDataReceived的事件处理程序,也可以使用lineReceived
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/16 7:53:21- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |