zoukankan      html  css  js  c++  java
  • python学习笔记(网络编程)

    Python 内置封装了很多常见的网络协议的库,因此Python成为了一个强大的网络编程工具,这里是对Python的网络方面编程的一个简单描述。

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

    socket模块

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

    一个小型服务器:

    #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的规则中。

    urllib和urllib2模块

    urllib 和 urllib2 是Python标准库中最强的的网络工作库。通过这两个库所提供的上层接口,使我们可以像读取本地文件一样读取网络上的文件。而且 urllib2 并不是 urllib 的升级版本(应该是一种补充),二者是不可相互替代的。

    通过使用 urllib 的 urlopen 函数可以很容易的打开远程的文件,如下:

    >>> 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:pythonmyDemogame.txt')
    >>> txt=webpage.read()
    >>> print txt
    蛋蛋 1 10 10
    
    
    >>> 

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

    >>> from urllib import urlretrieve
    >>> webpage=urlretrieve('http://www.baidu.com','f:pythonmyDemowebpage.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

    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()
            print 'Got connection from',addr
            self.wfile.write('Thank you for connecting')
    
    server=TCPServer(('',1234),handler)
    server.serve_forever()

    多连接

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

    • 分叉(forking)(windows 不支持)
    • 线程(threading)
    • 异步I/O(asynchronous I/O)

    使用分叉

    分叉(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()

     带有 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
                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

    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

    使用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.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()
  • 相关阅读:
    设置打印 页面 方向与大小
    设置对齐
    设置字体
    SVN版本管理与大型代码上线方案(一)
    项目案例之Pipeline流水线及流水线发布PHP项目(二)
    Jenkins企业应用进阶详解(一)
    iptables 防火墙(下)
    iptables 防火墙(上)
    zabbix生产环境案例(三)
    深入理解zabbix(二)
  • 原文地址:https://www.cnblogs.com/whats/p/4748183.html
Copyright © 2011-2022 走看看