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()
  • 相关阅读:
    remove white space from read
    optimize the access speed of django website
    dowload image from requests
    run jupyter from command
    crawl wechat page
    python version 2.7 required which was not found in the registry windows 7
    health
    alternate rows shading using conditional formatting
    word
    【JAVA基础】static 关键字
  • 原文地址:https://www.cnblogs.com/whats/p/4748183.html
Copyright © 2011-2022 走看看