zoukankan      html  css  js  c++  java
  • Python高级之Socket 探索(五)

    目录:

    • 面向对象
    • 反射
    • socket

    一、面向对象

    方法

    方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。

    普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
    类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
    静态方法:由类调用;无默认参数;

    class Aniaml:
        count = 10
        def __init__(self,name):
            self.name = name
            self.num = None
        hobbie = 'meat'
        @classmethod    #类方法,不能访问实例变量
        def talk(self):
            print('%s is talking ...'%self.hobbie )
        @staticmethod   #静态方法,不能访问类变量及实例变量
        def walk():
            print('is walking ...')
        @property   #把方法变属性
        def habbit(self):
            print('%s habit is sss'%self.name)
        @property
        def total_players(self):
            return self.num
        @total_players.setter
        def total_players(self,num):
            self.num = num
            print('total players:',self.num)
        @total_players.deleter
        def total_players(self):
            print('total player got deleted.')
            del self.num
    Aniaml.hobbie
    Aniaml.talk()
    
    d = Aniaml('hahah')
    print(d.total_players)
    d.total_players = 3
    类的特殊成员,内部模块
    
    class A:
        n = 'A'
        def f2(self):
            print('f2 from A')
    class B(A):
    
    
        n = 'B'
        def __init__(self):
            pass
        def f1(self):
            print('f1 from B')
        def f2(self):
            print('f2 from B')
        def __del__(self):
            print('del ....')
        def __call__(self, *args, **kwargs):
            print('__cal__')
    class C(A):
        n = 'C'
        def f2(self):
            print('f2 from C')
    class D(B,C):
        pass
    d = D()
    d.f1()
    d.f2()
    print(B.__doc__)
    print(B.__dict__)
    print(B.__class__)
    print(B.__module__)
    B.__del__
    obj = B()
    obj()

    二、反射


        Python中的反射功能由以下四个内置函数提供:

    • hasattr()    检查是否包含某成员
    • getattr()    获取成员
    • setattr()    设置成员
    • delattr()    删除成员


    1、从前我们最开始在写一些输入选项的时候会使用简单的if … else..来实现:

     raw = input(‘输入您的选择:’).strip()
        if raw == ‘start’:
            pass
        else raw == ‘stop’:
            pass


    2、后来学习了字典以后,我们发现原来可以精简一些:
       

    menu_dic = {'1':'start’,'2':'stop','3':'restart'}
        raw = input('请输入您的选择: ').strip()
        if raw in menu_dic:
          print(menu_dic[raw])


    3、再后来学习了反射后,我们发现原来还可以再精简一些:

    import sys
    class WebServer(object):
        def __init__(self,host,port):
            self.host = host
            self.port = port
        def start(self):
            print('Server is stating ...')
        def stop(self):
            print('Server is stopping ...')
        def restart(self):
            self.stop()
            self.start()
            print('Server is restarting ...')
    if __name__ == '__main__':
        server = WebServer('localhost',80)
        #hasatter 判断输入参数是否包含在class WebServer()
        if hasattr(server,sys.argv[1]):
        #如果包含,获取该成员
            func = getattr(server,sys.argv[1])
            func()
    $ python3 day07.py start
    Server is stating ...

        如果要设置一个新的成员,则需要使用setattr(),删除的话则要使用delattr(),修改为:

    def test_run(self,name):
         print('Test_running ...',name,self.host)
    if __name__ == '__main__':
         server = WebServer('localhost',80)
    if hasattr(server,sys.argv[1]):
        func = getattr(server,sys.argv[1])
         func()
    setattr(server,'run',test_run)
    server.run(server,'haha’)
    #运行结果
    Server is stating …
    Test_running ... haha localhost

    三、socket    


        socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
        socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。
        socket和file的区别:
    file模块是针对某个指定文件进行【打开】【读写】【关闭】
    socket模块是针对 服务器端 和 客户端Socket 进行【打开】【读写】【关闭】

    具体状态:


    sk.bind(address)
        将套接字绑定到地址。adress地址的格式取决于地址族。以元组(host,port)的形式表示地址。
    sk.listen(backlog)
        开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
        backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5.这个值不能无限大,因为内核中维护连接队列。
    sk.setblock(bool)
        是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。
    sk.accept()
        接受连接并返回(conn,address)其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。
        接收TCP客户的连接(阻塞式)等待连接的到来。
    sk.connect(adress)
        连接到address处的套接字。address格式为元组。如果连接出错,返回socket.error错误。
    sk.connect_ex(address)
        同上,区别是有返回值。连接成功返回0,失败则返回其他编码。
    sk.close()
        关闭套接字
    sk.recv(bufsize)
        接收套接字的数据。数据以字符串形式返回,bufsize可以指定最多可以接收的数量。
    sk.send(string)
        将str中的数据发送到连接的套接字。返回值是要发送的字节数量。
    sk.sendall(string)
        将str中的数据发送到连接的套接字,但在返回之前会尝试发送所有的数据。成功返回None,失败则抛出异常。
    sk.sendto(string,address)
        将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是是发送的字节数。该函数主要用于UDP协议。
    sk.settimeout(timeout)
        设置套接字操作的超时时间,最好在刚创建套接字时设置。
    sk.getpeername()
        返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)
    sk.getsockname()
        返回套接字自己的地址。
    sk.fileno()
        套接字的文件描述符。

    执行流程


    server 端:
        1、创建套接字,绑定套接字到本地IP和端口

     ip_port = ('127.0.0.1',9998)
     sk = socket.socket()
     sk.bind(ip_port)

        2、开始监听
            sk.listen(5)
        3、进入循环,不断接受客户端的连接请求
           

    while True:
            print('Server is waiting ... ‘)
            conn,addr = sk.accept()

        4、然后接收传来的数据,并发送给对方数据
            

     client_data = conn.recv(1024)
     print(str(client_data,'utf-8’))
     conn.sendall(bytes('这是 server !','utf-8’))

        5、传输完毕,关闭套接字
        sk.close()
    clinet端:
        1、创建套接字,绑定套接字到本地IP和端口
            

    ip_port = ('127.0.0.1',9998)
    sk  = socket.socket()
    sk.bind(ip_port)

        2、连接后发送数据和接受数据
            sk.sendall()
            sk.recv()
        3、传输完毕后,关闭套接字()
            sk.close()

    代码示例:实现client输入发送信息,server返回client输入的信息。

    #server端
    import socket
    ip_port = ('127.0.0.1',9998)
    sk  = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('Server is waiting ... ')
        conn,addr = sk.accept()
        client_data = conn.recv(1024)
        print(str(client_data,'utf-8'))
        conn.sendall(bytes('这是 server !','utf-8'))
        while True:
            client_data = conn.recv(1024)
            print('revv:',str(client_data,'utf8'))
            if not (client_data):break
            conn.sendall(client_data)
    #client端
    import socket
    ip_port = ('127.0.0.1',9998)
    
    sk = socket.socket()
    sk.connect(ip_port)
    
    sk.sendall(bytes('这是 client !','utf-8'))
    server_replay = sk.recv(1024)
    print(str(server_replay,'utf-8'))
    while True:
        client_raw = input(':').strip()
        sk.sendall(bytes(client_raw,'utf-8'))
        server_replay = sk.recv(1024)
        print(str(server_replay,'utf-8'))
    sk.close()

    代码示例:聊天工具

    #server端
    import
    socket ip_port = ('127.0.0.1',9998) sk = socket.socket() sk.connect(ip_port) sk.sendall(bytes('这是 client !','utf-8')) server_replay = sk.recv(1024) print(str(server_replay,'utf-8')) while True:
      #区别在这里,增加输入,然后返回 client_raw
    = input('>> ').strip() sk.sendall(bytes(client_raw,'utf-8')) server_replay = sk.recv(1024) print('server:',str(server_replay,'utf-8')) sk.close()
  • 相关阅读:
    【leetcode】9. Palindrome Number
    【leetcode】7. Reverse Integer
    【Leetcode】6. ZigZag Conversion
    Mysql读写分离
    Windows下为PHP安装redis扩展
    jquery 写的图片左右连续滚动
    PHP中spl_autoload_register函数的用法
    MySQL命令行查询乱码解决方法:
    AJAX 教程
    Mac安装composer爬过的坑
  • 原文地址:https://www.cnblogs.com/xiajie/p/5225713.html
Copyright © 2011-2022 走看看