zoukankan      html  css  js  c++  java
  • python学习day7

    目录

     一、反射

    二、socket

    三、socketserver


    一、反射

    python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。

     1 class Foo(object):
     2  
     3     def __init__(self):
     4         self.name = 'wupeiqi'
     5  
     6     def func(self):
     7         return 'func'
     8  
     9 obj = Foo()
    10  
    11 # #### 检查是否含有成员 ####
    12 hasattr(obj, 'name')
    13 hasattr(obj, 'func')
    14  
    15 # #### 获取成员 ####
    16 getattr(obj, 'name')
    17 getattr(obj, 'func')
    18  
    19 # #### 设置成员 ####
    20 setattr(obj, 'age', 18)
    21 setattr(obj, 'show', lambda num: num + 1)
    22  
    23 # #### 删除成员 ####
    24 delattr(obj, 'name')
    25 delattr(obj, 'func')

    详细解析:

    当我们要访问一个对象的成员时,应该是这样操作:

     1 class Foo(object):                                                 
    2 3 def __init__(self): 4 self.name = 'tom' 5 6 def func(self): 7 return 'func'
    8 9 obj = Foo() 10 11 # 访问字段 12 obj.name 13 # 执行方法 14 obj.func()

    那么问题来了?
    a、上述访问对象成员的 name 和 func 是什么? 
    答:是变量名
    b、obj.xxx 是什么意思? 
    答:obj.xxx 表示去obj中或类中寻找变量名 xxx,并获取对应内存地址中的内容。
    c、需求:请使用其他方式获取obj对象中的name变量指向内存中的值 “tom”
    1 class Foo(object):
    2  
    3     def __init__(self):
    4         self.name = 'tom'
    5  
    6 # 不允许使用 obj.name
    7 obj = Foo()
    View Code

    答:有两种方法,如下:

     1 class Foo(object):
     2 
     3     def __init__(self):
     4         self.name = 'alex'
     5 
     6     def func(self):
     7         return 'func'
     8 
     9 # 不允许使用 obj.name
    10 obj = Foo()
    11 
    12 print obj.__dict__['name']
    方法一
     1 class Foo(object):
     2 
     3     def __init__(self):
     4         self.name = 'alex'
     5 
     6     def func(self):
     7         return 'func'
     8 
     9 # 不允许使用 obj.name
    10 obj = Foo()
    11 
    12 print getattr(obj, 'name')
    方法二

    d、比较三种访问方式

    • obj.name
    • obj.__dict__['name']
    • getattr(obj, 'name')

    答:第一种和其他种比,...
          第二种和第三种比,...

    结论:反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!

     1 import sys
     2 
     3 class WebServer(object):
     4     def __init__(self,host,port):
     5         self.host = host
     6         self.port = port
     7 
     8     def start(self):
     9         print('start')
    10 
    11     def stop(self):
    12         print("stop")
    13 
    14     def restart(self):
    15         self.stop()
    16         self.start()
    17 
    18 if __name__ == "__main__":
    19     server = WebServer('localhost',333)
    20     if hasattr(server,sys.argv[1]):
    21         func = getattr(server,sys.argv[1])
    22         func()
    例子

    类也是对象

     1 class Foo(object):
     2  
     3     staticField = "old boy"
     4  
     5     def __init__(self):
     6         self.name = 'wupeiqi'
     7  
     8     def func(self):
     9         return 'func'
    10  
    11     @staticmethod
    12     def bar():
    13         return 'bar'
    14  
    15 print getattr(Foo, 'staticField')
    16 print getattr(Foo, 'func')
    17 print getattr(Foo, 'bar')

    模块也是对象

    1 #!/usr/bin/env python
    2 # -*- coding:utf-8 -*-
    3 
    4 def dev():
    5     return 'dev'
    home.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3  
     4 """
     5 程序目录:
     6     home.py
     7     index.py
     8  
     9 当前文件:
    10     index.py
    11 """
    12  
    13  
    14 import home as obj
    15  
    16 #obj.dev()
    17  
    18 func = getattr(obj, 'dev')
    19 func() 
    index.py

    二、socket

    socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。

    socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)

    socket和file的区别:

    • file模块是针对某个指定文件进行【打开】【读写】【关闭】
    • socket模块是针对 服务器端 和 客户端Socket 进行【打开】【读写】【关闭】

    socket服务端与客户端交流示意图:

    425762-20151212160019653-1079393936


    socket()模块函数

    使用socket.socket()函数来创建套接字,语法如下:

    socket(socket_family,socket_type,protocol=0)

    如前所述,参数一:socket_family(地址簇)

    socket.AF_UNIX    只能用于单一的UNIX系统进程间通信

    socket.AF_INET     IPV4(默认)

    socket.AF_INET6   IPV6

    参数二:socket_type(类型)

    socket.SOCK_STREAM 流式socket , for TCP (默认)
    socket.SOCK_DGRAM 数据报式socket , for UDP

    socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
    socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
    socket.SOCK_SEQPACKET 可靠的连续数据包服务

    参数三:protocol(协议)

    0 (默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议

    创建一个TCP/IP的套接字,你要这样调用socket.socket():

    tcpsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    同样的,创建一个UDP/IP的套接字,你要这样:

    udpsocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

    套接字对象(内建)方法:

    函数 描述
    服务器套接字函数  
    s.bind(address) 绑定地址(主机名,端口号对)到套接字
    s.listen(backlog) 开始TCP监听
    s.accept() 被动接受TCP客户端连接,(阻塞式)等待链接的到来
    客户端套接字函数  
    s.connect() 主动初始化TCP服务器连接
    s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
    公共用途的套接字函数  
    s.recv() 接收TCP数据
    s.send() 发送TCP数据
    s.sendall() 完整发送TCP数据(不停调用s.send())
    s.recvfrom() 接收UDP数据
    s.sendto() 发送UDP数据
    s.getpeername() 链接到当前套接字的远端的地址(TCP连接)
    s.getsockname() 当前套接字的地址
    s.getsockopt() 返回指定套接字的参数
    s.setsockopt() 设置指定套接字的参数
    s.close() 关闭套接字
    面向模块的套接字函数  
    s.setblocking() 设置套接字的阻塞与非阻塞模式
    s.settimeout() 设置阻塞套接字操作的超时时间
    s.gettimeout() 得到阻塞套接字操作的超时时间
    面向文件的套接字函数  
    s.fileno() 套接字的文件描述
    s.makefile() 创建一个与该套接字相关联的文件对象

    例:(win环境)

    server端

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import socket
    
    ip_port = ('127.0.0.1',9999)
    
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('server waiting...')
        conn,addr = sk.accept()
        client_data = conn.recv(1024)
        print(str(client_data,'utf8'))
        conn.sendall(bytes('不要回答,不要回答,不要回答','utf8'))
    
        conn.close()

    client端

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import socket
    ip_port = ('127.0.0.1',9999)
    
    sk = socket.socket()
    sk.connect(ip_port)
    
    sk.sendall(bytes('请求占领地球','utf8'))
    
    server_reply = sk.recv(1024)
    print(str(server_reply,'utf8'))
    
    sk.close()

    连续交互通信实例:

    server端:(win环境)

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import socket
    
    ip_port = ('127.0.0.1',9999)
    
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('server waiting...')
        conn,addr = sk.accept()
        client_data = conn.recv(1024)
        print(str(client_data,'utf8'))
        conn.sendall(bytes('不要回答,不要回答,不要回答','utf8'))
        while True:
            try:
                client_data = conn.recv(1024)
                print(str(client_data,'utf8'))
                server_response = input('>>>:').strip()
                
            except Exception:
                print("client closed,break")
                break
            conn.send(bytes(server_response,'utf8'))
        conn.close()

    server端:(Linux环境)

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import socket
    
    ip_port = ('127.0.0.1',9999)
    
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('server waiting...')
        conn,addr = sk.accept()
        client_data = conn.recv(1024)
        print(str(client_data,'utf8'))
        conn.sendall(bytes('不要回答,不要回答,不要回答','utf8'))
        while True:
            client_data = conn.recv(1024)
            print(str(client_data,'utf8'))
            server_response = input('>>>:').strip()
    if not client_data:break
            conn.send(server_response)
    
        conn.close()

    client端:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import socket
    ip_port = ('127.0.0.1',9999)
    
    sk = socket.socket()
    sk.connect(ip_port)
    
    sk.sendall(bytes('请求占领地球','utf8'))
    server_reply = sk.recv(1024)
    print(str(server_reply,'utf8'))
    while True:
        user_input = input(">>>").strip()
        sk.send(bytes(user_input,'utf8'))
        server_reply = sk.recv(1024)
        print(str(server_reply,'utf8'))
    
    sk.close()

    模拟实现简单ssh功能:

    server端:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import socket
    import subprocess
    ip_port = ('127.0.0.1',9999)
    
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('server waiting...')
        conn,addr = sk.accept()
        while True:
            client_data = conn.recv(1024)
            if not client_data:break
            print("recv cmd:",str(client_data,'utf8'))
            cmd = str(client_data,'utf8').strip()
            cmd_call = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
            cmd_result = cmd_call.stdout.read()
            if len(cmd_result) == 0:
                cmd_result = b"cmd execution has no output..."
            ack_msg = bytes("CMD_RESULT_SIZE|%s"%len(cmd_result),"utf8")
            conn.send(ack_msg)
            client_ack = conn.recv(50)
            if client_ack.decode() == "CLIENT_READY_TO_RECV":
                conn.send(cmd_result)
    
        conn.close()

    client端:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import socket
    ip_port = ('127.0.0.1',9999)
    
    sk = socket.socket()
    sk.connect(ip_port)
    while True:
        user_input = input("cmd:").strip()
        if len(user_input) == 0:continue
        if user_input == "q":break
        sk.send(bytes(user_input,'utf8'))
        #ack_msg = b"CMD_RESULT_SIZE|%s",len(cmd_result)
        server_ack_msg = sk.recv(100)
        cmd_res_msg = str(server_ack_msg.decode()).split("|")
        print("server response:",cmd_res_msg)
        if cmd_res_msg[0] == "CMD_RESULT_SIZE":
            cmd_res_size = int(cmd_res_msg[1])
            sk.send(b"CLIENT_READY_TO_RECV")
        res = ''
        received_size = 0
        while received_size < cmd_res_size:
            data = sk.recv(500)
            received_size += len(data)
            res += str(data.decode())
        else:
            print(str(res))
            print("----------recv doen----------")
    sk.close()

    三、sockeserver

    SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。

    425762-20151226114322968-1230975336

    例:

    server端:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import socketserver
    class MyTCPHandler(socketserver.BaseRequestHandler):
        def setup(self):
            print("Building secure connection chanel...")
        def handle(self):
            print("New Conn:",self.client_address)
            while True:
    
                data = self.request.recv(1024)
                if not data:break
                print("Client Says:",data.decode())
                self.request.send(data)
        def finish(self):
            print("client conn is done...")
    if __name__ == '__main__':
        HOST, PORT = "localhost", 50007
        # 把刚才写的类当作一个参数传给ThreadingTCPServer这个类,下面的代码就创建了一个多线程socket server
        server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
        # 启动这个server,这个server会一直运行,除非按ctrl-C停止
        server.serve_forever()

    client端:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import socket
    ip_port = ('127.0.0.1',50007)
    
    sk = socket.socket()
    sk.connect(ip_port)
    while True:
        msg = input(">>:").strip()
        sk.sendall(bytes(msg,'utf8'))
        server_reply = sk.recv(1024)
        print("Server Reply:",str(server_reply,'utf8'))
    sk.close()
  • 相关阅读:
    Use Eclipse to develop groovy[docs.codehaus.org]
    Map.putAll方法——追加另一个Map对象到当前Map集合(转)
    限制某个进程只能在某个CPU上运行
    Java实现蓝桥杯 算法提高 身份证号码升级
    Java实现蓝桥杯 算法提高 身份证号码升级
    Java实现蓝桥杯 算法提高 身份证号码升级
    Java实现蓝桥杯 算法提高 身份证号码升级
    Java蓝桥杯 算法训练 复数归一化
    Java实现 蓝桥杯 算法提高 最大乘积
    Java实现 蓝桥杯 算法训练 p1103
  • 原文地址:https://www.cnblogs.com/spykids/p/5279848.html
Copyright © 2011-2022 走看看